数据结构——顺序表(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. }

       完!

相关文章
|
15天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
90 9
|
29天前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
60 4
|
14天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
57 16
|
14天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
63 8
|
17天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
44 4
|
18天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
18天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
50 3
|
18天前
|
存储 算法 C语言
C语言数据结构(2)
【10月更文挑战第21天】
|
18天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
29天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】
《趣学C语言和数据结构100例》精选5个编程问题,涵盖求最大公约数与最小公倍数、字符统计、特殊序列求和及阶乘计算等,通过实例讲解C语言基础与算法思维,适合初学者实践学习。
69 1