【数据结构和算法】实现线性表中的静态、动态顺序表(上)

简介: 【数据结构和算法】实现线性表中的静态、动态顺序表

本文是数据结构的开篇,上文学习了关于使用C语言实现静态、动态、文件操作的通讯录,其中使用到了结构体这一类型,实际上,是可以属于数据结构的内容,接下来我们来了解一下顺序表的相关内容。

前言

数据结构是什么?

对于大家来说,这是一个全新的内容模块,数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法索引技术有关。

我们接下来是对于数据结构的顺序表的实现的讲解


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

实际上,学会了顺序表和链表,自然栈、队列、二叉树等各种结构就好学啦,又称顺序表和链表是数据结构的基础,是实现后序内容的基础。

一、顺序表是什么?

1.将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构顺序结构

2.使用顺序结构存储的线性表叫做顺序表

总结:

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

二、分析顺序表的实现

顺序表,分为动态和静态两种顺序表,顺序表的实际操作功能大致为,增删改查,又细分为头尾增删,初始化、摧毁顺序表等操作。

我们接下来分别介绍静态和动态顺序表是如何实现的!!!

三、静态顺序表

使用结构体为:

1.顺序表初始化

如图所示:

代码演示:

//初始化函数
void InitSeqtable(Seqtable* st) {
  //for (int i = 0; i < MAX; i++) {
  //  st->date[i] = 0;//初始化为0  实际上可以不用初始化数组
  //}
  st->size = 0;
}

2.增加元素

分为头插入、尾插入

1.尾插

如图所示:

代码演示:

//尾插入
void BackSeqtable(Seqtable* st, int data) {
  //尾部插入的时候要进行判别是否为满
  if (st->size == MAX) {
    //表示满了
    perror("顺序表已经满员,无法插入新数据\n");
    exit(-1);//退出就可以
  }
  //没有满员,就加入数据即可
  st->date[st->size++] = data;
}

2.头插

如图所示:

代码如下:

//头插入
void FrontSeqtable(Seqtable* st, int data) {
  //一样先进行判断是否满员
  if (st->size == MAX) {
    perror("满员无法插入");
    exit(-1);
  }
  //头部插入。就是将原有数据向后移动一个位置
  int num = st->size - 1;
  for (int i = num; i>=0; i--) {
    st->date[i + 1] = st->date[i];
  }
  //while (num>=0) {
  //  st->date[num + 1] = st->date[num];
  //  num--;
  //}
  //最后插入数据
  st->date[0] = data;
  st->size++;
}

3.删除元素

分为头删、尾删

1.尾删

如图所示:

代码如下:

//尾删除
void SeqtablePopBack(Seqtable* st) {
  //尾删除,需要判断是否为空
  assert(st->size > 0);//断言判断
  st->size--;//直接元素个数减去一个就可以
}

2.头删

如图所示:

代码如下:

//头删除
void SeqtablePopFront(Seqtable* st) {
  //头部删除,也要判空
  assert(st->size > 0);//断言
  //将后面的数据覆盖前面的数据
  for (int i = 0; i < st->size-1; i++) {
    st->date[i] = st->date[i + 1];
  }
  st->size--;//size减去一个元素即可
}

4.改变数据和查找

想要改变指定下标的数据,输入要查找的元素,更改这个的数据,要先查找到对应坐标,简易的更改数值,不考虑重复的问题,从左向右的顺序查询

代码如下:

//查找
int SearchSeqtable(Seqtable* st) {
  assert(st->size > 0);//如果为空,不用查找,直接报错
  int num = 0;
  scanf("%d", &num);//输入查找的元素
  for (int i = 0; i < st->size; i++) {
    if (st->date[i] == num) {
      return i;//找到返回下标
    }
  }
  return -1;//没找到返回-1
}
void ChangeSeqtable(Seqtable* st) {
  int num=SearchSeqtable(st);//进入查找,返回下标
  if (num == -1) {
    printf("顺序表中没有该元素,无法修改\n");
    return;
  }
  int a = 0;
  scanf("%d", &a);//输入想要更改的数据
  st->date[num] = a;
}

5.打印和销毁顺序表

代码如下:

//摧毁顺序表
void SeqtableDestory(Seqtable* st) {
  //摧毁的话,静态表直接初始化为0
  st->size = 0;
}
//打印
void PrintSeqtable(Seqtable* st) {
  for (int i = 0; i < st->size; i++) {
    printf("%d ", st->date[i]);
  }
}

四、动态顺序表

动态顺序表和静态顺序表的差别就是结构体、初始化、摧毁顺序表、扩容

结构体如下:

//动态顺序表
typedef struct Seqtable {
  int* data;//数据域
  int size;//个数
  int capacity;//容量
}Seqtable;
//实际上动态顺序表和静态顺序表,只有在初始化、销毁、扩容的时候不一样

1.初始化

//初始化顺序表
void InitSeqtable(Seqtable* st) {
  st->size = st->capacity = 0;
  st->data = NULL;
}

2.扩容

如图所示:

代码演示:

//扩容
void Expansion(Seqtable* st) {
  //1.直接扩容二倍,这样防止后序一致扩容
  int newcapacity = st->capacity = 0 ? 4 : st->capacity * 2;
  int* tmp = (int*)realloc(st->data, newcapacity * sizeof(int));
  if (tmp == NULL) {
    //表示创建失败
    perror("realloc fail\n");
    exit(-1);
  }
  //创建成功  tmp给data
  st->data = tmp;
  st->capacity = newcapacity;
}

如图上,另外一种扩容方法,可以看这篇文章中动态通讯录扩容,里面有介绍(24条消息) 【C语言】使用C语言实现静态、动态的通讯录(简单易懂)_小王学代码的博客-CSDN博客

3.销毁顺序表

void SeqListDestory(Seqtable* ps) {
  free(ps->data);//直接释放a的空间 
  ps->data = NULL;//然后指向NULL
  ps->capacity = ps->size = 0;
}

除此之外,和静态顺序表都差不多一样了

相关文章
|
3月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
74 1
|
3月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
172 4
|
23天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
41 2
|
2月前
|
存储 运维 监控
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
58 20
|
3月前
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
|
3月前
|
数据采集 存储 算法
Python 中的数据结构和算法优化策略
Python中的数据结构和算法如何进行优化?
|
3月前
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
137 23
|
3月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
86 1
|
3月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
307 9
|
3月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
48 1