数据结构——顺序表(C语言)

简介: 数据结构——顺序表(C语言)

一、顺序表概念

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

二、顺序表分类

       1.静态顺序表

       概念:使⽤定⻓数组存储元素

       2.动态顺序表

       使用动态开辟的数组存储元素

       动态顺序表可根据我们的需要分配空间大小

       size 表示当前顺序表中已存放的数据个数

       capacity 表示顺序表总共能够存放的数据个数

       我们现在是明白了动态顺序表和动态,那我们在用代码实现顺序表时会用那种呢?相信大家此时都已经有了答案,答案很显然是动态顺序表。因为动态顺序表比静态顺序表更加的灵活,不会那么死板,好话不多说,咱们一起来实现吧!

三、顺序表的实现

       1.顺序表的结构体定义

       这里说明一下:数据结构这方面主要是:数组、指针、结构体这方面内容,因此数据结构可以让我们更好的理解以上内容。

       我们实现顺序表一共会用两个源文件和一个头文件,具体为什么,扫雷里说过可自行查阅。

1. typedef int seqlist;//大家可想一想把int 命名成seqlist的好处
2. typedef struct Seqlist
3. {
4.  seqlist* a;
5.  int  size;//有效数据个数
6.  int capacity;//总容量
7. }sl;//结构体命名

       2. 顺序表初始化

       当我们拥有了一个顺序表我们必然要对其初始化。

1. void SLInit(SL* ps)
2. {
3.  ps->a = NULL;//初始化把指针置为空
4.  ps->capacity = ps->size = 0;//元素个数均为零
5. }

       3.顺序表销毁

       既然把顺序表初始化了,必然要对其销毁

1. void SLDestroy(SL* ps)
2. {
3.  free(ps->a);//顺序表在后续会使用内存函数需free释放
4.  ps->a = NULL;
5.  ps->capacity = ps->size = 0;
6. }

       4.顺序表的检验

       记住写出一个函数就要对其进行检验。

1. void test1()
2. {
3.  void SLInit(SL * ps);
4.  void SLDestroy(SL * ps);
5. }

       当我们写出此代码时会报错,这是为什么呢?答案是test文件中只包含了头文件的,没包含源文件的(源文件相互包含会报错),这时我们添加以下代码即可:

SL ps;

       这个时候我们进行调试即可。

       5.顺序表打印

1. void SLPrint(SL* ps)
2. {
3.  for (int i = 0; i < ps->size; i++)
4.  {
5.    printf("%d", ps->a[i]);
6.  }
7.  peintf("\n");
8. }

       6.顺序表扩容

       众所周知顺序表有这四大功能:增删查改,要进行第一个功能便要对顺序表经行扩容。

1. void SLCheckCapacity(SL* ps)
2. {
3.  if (ps->capacity == ps->size)
4.  {
5.    int newcapacity = ps->capacity > 0 ? 2 * ps->capacity : 4;//这里使用了三目操作符
6.    //定义一个变量来接收,出第一次外每次扩容二倍
7.    //为什么是二倍这里不过多推理,可自行了解
8.    SL* p = (SL *)realloc(ps->a, newcapacity*sizeof(seqlist));
9.    if (p == NULL)
10.     {
11.       printf("扩容失败\n");
12.       exit(1);
13.     }
14.     ps->a = p;
15.     ps->capacity = newcapacity;
16.   }
17. }

       切记:一定要在if语句里进行操作

       大家可自行对其检验,这里不再进行。

       7.顺序表尾插与头插

       接下来实现顺序表这个功能:

       尾插:

1. void SLPushBack(SL* ps, seqlist x)
2. {
3.  SLCheckCapacity(ps);//检验元素是否满
4.  ps->a[ps->size++] = x;
5.  //也可采取以下这种
6.  //ps->a[pa->size]=x;   
7.  //ps->size++;
8. }

       头插:

1. void SLPushFront(SL* ps, seqlist x)
2. {
3.  SLCheckCapacity(ps);//检验元素是否满
4.  for (int i = ps->size-1; i >0; i--)
5.  {
6.    ps->a[i+1] = ps->a[i];
7.  }
8.  ps->size++;
9.  ps->a[0] = x;
10. }

       8.尾删与头删

       尾删:

1. void SLPopBack(SL* ps)
2. {
3. assert(ps);
4.  ps->size--;
5. }

       头删:

1. void SLPopFront(SL* ps)
2. {
3.  assert(ps);
4.  for (int i = 0; i < ps->size-1; i++)
5.  {
6.    ps->a[i] = ps->a[i + 1];
7.  }
8.  ps->size--;
9. }

       9.在pos处插入数据

1. void SLInsert(SL* ps, int pos, SLDataType x)
2. {
3.  assert(ps);
4.  assert(pos > 0 && pos <= ps->size);
5.  SLCheckCapacity(ps);
6.  for (int i = ps->size; i > pos; i--)
7.  {
8.    ps->a[i] = ps->a[i-1];
9.  }
10.   ps->size++;
11.   ps->a[pos] = x;
12. }

       10.在pos处删除数据

1. void SLErase(SL* ps, int pos)
2. {
3.  assert(ps);
4.  assert(pos > 0 && pos <= ps->size);
5.  for (int i = pos - 1; i < ps->size-1; i++)
6.  {
7.    ps->a[i] = ps->a[i+1];
8.  }
9.  ps->size--;
10. }

       11.查找数据

1. int SLFind(SL* ps, seqlist x)
2. {
3.  assert(ps);
4.  for (int i = 0; i < ps->size - 1; i++)
5.  {
6.    if (ps->a[i] == x)
7.    {
8.      printf("找到了,下标为: %d \n", i + 1);
9.      return i;
10.     }
11.   }
12.   printf("没找到\n");
13.   return -1;
14. }

四、全部文件及测试结果

       seqlist.h:

1. #pragma once
2. #include<stdio.h>
3. #include<stdlib.h>
4. #include<assert.h>
5. typedef int seqlist;//大家可想一想把int 命名成seqlist的好处
6. typedef struct Seqlist
7. {
8.  seqlist* a;
9.  int  size;//有效数据个数
10.   int capacity;//总容量
11. }SL;
12. void SLInit(SL* ps);//顺序表初始化
13. void SLDestroy(SL* ps);//顺序表销毁
14. void SLPrint(SL* ps);//顺序表打印
15. void SLCheckCapacity(SL* ps);//顺序表扩容
16. void SLPushBack(SL* ps, seqlist x);//尾插
17. void SLPopBack(SL* ps);//尾删
18. void SLPushFront(SL* ps, seqlist x);//头插
19. void SLPopFront(SL* ps);//头删
20. void SLInsert(SL* ps, int pos, seqlist x);//特定位置插入数据
21. void SLErase(SL* ps, int pos); //特定位置删除数据
22. int SLFind(SL* ps, seqlist x);//查找数据

       seqlist.c:

1. #include"seqlist.h"
2. void SLInit(SL* ps)
3. {
4.  ps->a = NULL;//初始化把指针置为空
5.  ps->capacity = ps->size = 0;//元素个数均为零
6. }
7. void SLDestroy(SL* ps)
8. {
9.  free(ps->a);//顺序表在后续会使用内存函数需free释放
10.   ps->a = NULL;
11.   ps->capacity = ps->size = 0;
12. }
13. void SLPrint(SL* ps)
14. {
15.   for (int i = 0; i < ps->size; i++)
16.   {
17.     printf("%d", ps->a[i]);
18.   }
19.   peintf("\n");
20. }
21. void SLCheckCapacity(SL* ps)
22. {
23.   if (ps->capacity == ps->size)
24.   {
25.     int newcapacity = ps->capacity > 0 ? 2 * ps->capacity : 4;//这里使用了三目操作符
26.     //定义一个变量来接收,出第一次外每次扩容二倍
27.     //为什么是二倍这里不过多推理,可自行了解
28.     SL* p = (SL *)realloc(ps->a, newcapacity*sizeof(seqlist));
29.     if (p == NULL)
30.     {
31.       printf("扩容失败\n");
32.       exit(1);
33.     }
34.     ps->a = p;
35.     ps->capacity = newcapacity;
36.   }
37. }
38. void SLPushBack(SL* ps, seqlist x)
39. {
40.   SLCheckCapacity(ps);//检验元素是否满
41.   ps->a[ps->size++] = x;
42.   //也可采取以下这种
43.   //ps->a[pa->size]=x;   
44.   //ps->size++;
45. }
46. void SLPushFront(SL* ps, seqlist x)
47. {
48.   SLCheckCapacity(ps);//检验元素是否满
49.   for (int i = ps->size-1; i >0; i--)
50.   {
51.     ps->a[i+1] = ps->a[i];
52.   }
53.   ps->size++;
54.   ps->a[0] = x;
55. }
56. void SLPopBack(SL* ps)
57. {
58.   assert(ps);
59.   ps->size--;
60. }
61. void SLPopFront(SL* ps)
62. {
63.   assert(ps);
64.   for (int i = 0; i < ps->size-1; i++)
65.   {
66.     ps->a[i] = ps->a[i + 1];
67.   }
68.   ps->size--;
69. }
70. void SLInsert(SL* ps, int pos, SLDataType x)
71. {
72.   assert(ps);
73.   assert(pos > 0 && pos <= ps->size);
74.   SLCheckCapacity(ps);
75.   for (int i = ps->size; i > pos; i--)
76.   {
77.     ps->a[i] = ps->a[i-1];
78.   }
79.   ps->size++;
80.   ps->a[pos] = x;
81. }
82. void SLErase(SL* ps, int pos)
83. {
84.   assert(pos >= 0 && pos < ps->size && ps);
85.   for (int i = pos+1; i < ps->size-1; i++)
86.   {
87.     ps->a[i-1] = ps->a[i];
88.   }
89.   ps->size--;
90. }
91. int SLFind(SL* ps, seqlist x)
92. {
93.   assert(ps);
94.   for (int i = 0; i < ps->size - 1; i++)
95.   {
96.     if (ps->a[i] == x)
97.     {
98.       printf("找到了,下标为: %d \n", i + 1);
99.       return i;
100.    }
101.  }
102.  printf("没找到\n");
103.  return -1;
104. }

       test.c:

1. #include"seqlist.h"
2. void menu()
3. {
4.  printf("***********************\n");
5.  printf("**1.尾插     2.尾删****\n");
6.  printf("**3.头插     4.头删****\n");
7.  printf("**5.固定插入 6.固定删除\n");
8.  printf("**7.查找     0.删除顺序表\n");
9.  printf("**0.销毁并退出*********\n");
10. }
11. int main()
12. {
13.   SL ps;
14.   SeqListInit(&ps);
15.   SeqListPushBack(&ps, 4);
16.   SeqListPushBack(&ps, 5);
17.   SeqListPushBack(&ps, 6);
18.   SeqListPushFront(&ps, 3);
19.   SeqListPushFront(&ps, 2);
20.   SeqListPushFront(&ps, 1);
21.   SeqListPrint(&ps);//顺序表初始化
22.   int input;
23.   do
24.   {
25.     menu();
26.     printf("please input your choice:");
27.     scanf("%d", &input);
28.     Seqlist x;
29.     int pos;
30.     int find;
31.     int getfind;
32.     switch (input)//顺序表输入测试
33.     {
34.     case 0:
35.       SeqListDestroy(&ps);
36.       break;
37.     case 1:
38.       scanf("%d", &x);
39.       SeqListPushBack(&ps, x);
40.       SeqListPrint(&ps);
41.       break;
42.     case 2:
43.       SeqListPopBack(&ps);
44.       SeqListPrint(&ps);
45.       break;
46.     case 3:
47.       scanf("%d", &x);
48.       SeqListPushFront(&ps, x);
49.       SeqListPrint(&ps);
50.       break;
51.     case 4:
52.       SeqListPopFront(&ps);
53.       SeqListPrint(&ps);
54.       break;
55.     case 5:
56.       scanf("%d", &pos);
57.       scanf("%d", &x);
58.       SeqListInsert(&ps, pos, x);
59.       SeqListPrint(&ps);
60.       break;
61.     case 6:
62.       scanf("%d", &pos);
63.       SeqListErase(&ps, pos);
64.       SeqListPrint(&ps);
65.       break;
66.     case 7:
67.       scanf("%d", &find);
68.       getfind = SeqListFind(&ps, find);
69.       printf("%d", getfind);
70.       printf("\n");
71.       break;
72.     default:
73.       printf("error input\n");
74.       break;
75.     }
76.   } while (input);
77.   return 0;
78. }

       完!

相关文章
|
28天前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
45 1
|
1月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
49 4
|
1月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
45 4
|
1月前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
46 4
|
1月前
|
算法 数据可视化 数据建模
【趣学C语言和数据结构100例】76-80
本文介绍了五种图论算法的C语言实现,涵盖二叉树的层次遍历及广度优先搜索(BFS)和深度优先搜索(DFS)的邻接表与邻接矩阵实现。层次遍历使用队列按层访问二叉树节点;BFS利用队列从源节点逐层遍历图节点,适用于最短路径等问题;DFS通过递归或栈深入图的分支,适合拓扑排序等场景。这些算法是数据结构和算法学习的基础,对提升编程能力和解决实际问题至关重要。
52 4
|
1月前
|
存储 算法 vr&ar
【趣学C语言和数据结构100例】71-75
本文介绍了五个C语言数据结构问题及其实现,涵盖链表与二叉树操作,包括按奇偶分解链表、交换二叉树左右子树、查找节点的双亲节点、计算二叉树深度及求最大关键值。通过递归和遍历等方法,解决了理论与实际应用中的常见问题,有助于提升编程能力和数据结构理解。
43 4
|
1月前
|
存储 算法 C语言
【趣学C语言和数据结构100例】66-70
本书《趣学C语言和数据结构100例》精选了5个典型的数据结构问题及C语言实现,涵盖链表与数组操作,如有序集合的集合运算、有序序列表的合并、数组中两顺序表位置互换、三递增序列公共元素查找及奇偶数重排。通过详细解析与代码示例,帮助读者深入理解数据结构与算法设计的核心思想,提升编程技能。
36 4
|
1月前
|
存储 算法 C语言
【趣学C语言和数据结构100例】51-55
本文介绍了五个关于链表操作的C语言实现案例,包括删除单链表中的重复元素、从两个有序链表中查找公共元素、判断一个链表是否为另一链表的连续子序列、判断循环双链表是否对称及合并两个循环单链表。每个案例都详细解析了算法思路与实现方法,涵盖了链表操作的多种场景,旨在帮助读者深入理解链表数据结构的应用,提升算法设计与编程能力。
43 4
|
1月前
|
存储 算法 C语言
【趣学C语言和数据结构100例】16-20
本文精选了五个C语言编程问题,涵盖数组操作、字符串处理等基础领域。包括查找二维数组中的鞍点、折半查找法、统计文章中字符数量、电文解密及字符串连接。每个问题都附有详细的代码实现与分析,旨在帮助读者理解算法逻辑,提升编程技巧。通过这些实践,不仅能锻炼编程能力,还能加深对数据结构和算法的理解,为未来的学习和工作打下坚实基础。
66 4
|
3天前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充