【数据结构】顺序表-C语言版(一)

简介: 【数据结构】顺序表-C语言版

线性表

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

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

 

顺序表及其特点

数组缺陷:定义数组时必须指定数组大小,但是如果指定的大小不能满足使用空间需求时,就会有问题。

顺序表含义及特点:顺序表本质是数组,是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改,顺序表要从左往右连续存储数据。顺序表的逻辑结构和物理结构都是连续的

2.顺序表分类:顺序表有两种,包括静态顺序表和动态顺序表

(1) 静态顺序表:使用定长数组存储元素。

1. //顺序表的静态存储
2. #define N 7
3. typedef int SLDataType;
4. 
5. typedef struct SeqList
6. {
7.  SLDataType array[N];//定长数组
8.  size_t size;//有效数据的个数
9. }SeqList;

(2)动态顺序表:使用动态开辟的数组存储。

1. typedef struct SeqList
2. {
3.  SLDataType* array;//指向动态开辟的数组
4.  size_t size;//有效数据的个数
5.  size_t capacity;//容量
6. }SeqList;

3. 顺序表缺陷:

(1)动态增容有性能消耗。

(2)当头部插入数据时,需要挪动数据


顺序表的实现

静态顺序表容量是固定的,因此静态顺序表不实用。那么如何实现动态顺序表呢?

18-dynamicSequenceTable.h(结构体定义和方法声明)

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. #pragma once
3. 
4. //为int类型重新定义新名称
5. //如果后续想把SeqList中成员*a的类型改为float或char,不需要把每个使用*a的地方都修改一遍,直接修改typdef定义类型即可
6. typedef int SeqDataType;
7. 
8. typedef struct SeqList
9. {
10.   SeqDataType* a;
11.   int size;//有效数据的个数
12.   int capacity;//容量
13. }SeqList,SEQ;
14. 
15. //内存中管理数据的结构增删改查的接口
16. 
17. //初始化
18. void SeqListInit(SeqList* seq);
19. 
20. //销毁
21. void SeqListDestroy(SeqList* seq);
22. 
23. //打印
24. void SeqListPrint(SeqList* seq);
25. 
26. //扩容
27. void SeqCheckCapacity(SeqList* seq);
28. 
29. //尾插
30. void SeqListPushBack(SeqList* seq, SeqDataType x);
31. 
32. //头插
33. void SeqListPushFront(SeqList* seq, SeqDataType x);
34. 
35. //尾删
36. void SeqListPopBack(SeqList* seq);
37. 
38. //头删
39. void SeqListPopFront(SeqList* seq);
40. 
41. //查找
42. int SeqListFind(SeqList* seq, SeqDataType x);
43. 
44. //某一位置插入数据
45. void SeqListInsert(SeqList* seq, int pos, SeqDataType x);
46. 
47. //某一位置删除数据
48. void SeqListErase(SeqList* seq, int pos);
49. 
50. //某一位置删除数据
51. void SeqListModify(SeqList* seq, int pos,SeqDataType x);

18-dynamicSequenceTable.c(方法实现)

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. #include<stdio.h>
3. #include<assert.h>
4. #include<stdlib.h>
5. 
6. #include "18-dynamicSequenceTable.h"
7. 
8. //初始化
9. void SeqListInit(SeqList* pq)
10. {
11.   assert(pq);
12. 
13.   //初始化每个成员变量的值
14.   pq->a = NULL;
15.   pq->size = 0;
16.   pq->capacity = 0;
17. }
18. 
19. //销毁
20. void SeqListDestroy(SeqList* pq)
21. {
22.   assert(pq);
23.   free(pq->a);
24.   pq->a = NULL;
25.   pq->size = 0;
26.   pq->capacity = 0;
27. }
28. 
29. //扩容
30. void SeqCheckCapacity(SeqList* pq)
31. {
32.   //判断是否需要扩容
33.   if (pq->size == pq->capacity)
34.   {
35.     //如果capacity=0,就申请4个a的空间,如果不为0,就申请2倍大的capacity的空间
36.     //一般扩容都扩容成原来2倍,太小则需要频繁扩容,太大则有可能浪费较多空间
37.     int newCapacity = pq->capacity == 0 ? 4 : pq->capacity * 2;
38.     SeqDataType* newA = (SeqDataType*)realloc(pq->a, sizeof(SeqDataType) * newCapacity);
39.     if (newA == NULL)
40.     {
41.       printf("realloc fail\n");
42.       return;
43.     }
44.     pq->a = newA;
45.     pq->capacity = newCapacity;
46.   }
47. }
48. 
49. //尾插
50. void SeqListPushBack(SeqList* pq, SeqDataType x)
51. {
52.   assert(pq);
53. 
54.   //判断是否需要扩容
55.   SeqCheckCapacity(pq);
56. 
57.   //把第size个元素值置为x
58.   pq->a[pq->size] = x;
59. 
60.   //size++
61.   pq->size++;
62. }
63. 
64. //头插
65. void SeqListPushFront(SeqList* pq, SeqDataType x)
66. {
67.   assert(pq);
68. 
69.   //判断是否需要扩容
70.   SeqCheckCapacity(pq);
71. 
72.   //在第一个位置插入数据需要把所有元素向后挪动一个位置,要从最后一个元素开始依次把所有数据拷贝到下一个位置
73.   int end = pq->size-1;
74.   while (end>=0)
75.   {
76.     //将元素拷贝到该元素下一个位置
77.     pq->a[end + 1] = pq->a[end];
78.     end--;
79.   }
80. 
81.   //将x放在第一个位置
82.   pq->a[0] = x;
83. 
84.   //size++
85.   pq->size++;
86. }
87. 
88. //打印
89. void SeqListPrint(SeqList* pq)
90. {
91.   assert(pq);
92.   int i = 0;
93.   for (i = 0; i < pq->size; i++)
94.   {
95.     printf("%d ", pq->a[i]);
96.   }
97.   printf("\n");
98. }
99. 
100. //尾删
101. void SeqListPopBack(SeqList* pq)
102. {
103.  assert(pq);
104.  assert(pq->size>0);
105. 
106.  //直接将元素个数-1即可,数据删除不删除无所谓
107.  pq->size--;
108. }
109. 
110. //头删
111. void SeqListPopFront(SeqList* pq)
112. {
113.  assert(pq);
114.  assert(pq->size > 0);
115.  int begin = 0;
116.  while (begin < pq->size)
117.  {
118.    //删除第一个元素,需要从前往后将其余元素依次拷贝到数组中,如果从后往前拷贝,那么所有元素值都为最后一个元素值
119.    pq->a[begin] = pq->a[begin + 1];
120.    begin++;
121.  }
122. 
123.  //size-1
124.  pq->size--;
125. }
126. 
127. //查找
128. int SeqListFind(SeqList* pq, SeqDataType x)
129. {
130.  assert(pq);
131.  int i = 0;
132.  for (i = 0; i < pq->size; i++)
133.  {
134.    if (pq->a[i] = x)
135.    {
136.      return i;
137.    }
138.  }
139. 
140.  return -1;
141. }
142. 
143. //某一位置插入数据
144. void SeqListInsert(SeqList* pq, int pos, SeqDataType x)
145. {
146.  assert(pq);
147.  assert(pos>0 && pos < pq->size);
148. 
149.  //判断是否需要扩容
150.  SeqCheckCapacity(pq);
151. 
152.  //从后往前拷贝数据
153.  int i = pq->size-1;
154.  while (i >= pos)
155.  {
156.    pq->a[i + 1] = pq->a[i];
157.    i--;
158.  }
159. 
160.  pq->a[pos] = x;
161.  pq->size++;
162. }
163. 
164. //某一位置删除数据
165. void SeqListErase(SeqList* pq, int pos)
166. {
167.  assert(pq);
168.  assert(pos > 0 && pos < pq->size);
169. 
170.  int i = pos;
171.  while (i < pq->size)
172.  {
173.    pq->a[i] = pq->a[i + 1];
174.    i++;
175.  }
176.  pq->size--;
177. }
178. 
179. //修改某一位置数据
180. void SeqListModify(SeqList* pq, int pos, SeqDataType x)
181. {
182.  assert(pq);
183.  assert(pos >= 0 && pos < pq->size);
184. 
185.  pq->a[pos] = x;
186. }

头插需要从后向前拷贝的原因:如果从前向后对数组依次拷贝,先拷贝1,最后拷贝5,就会把所有数据都变成小标为0的元素,因此要从后向前拷贝,先拷贝5,最后拷贝1。

18-test.c(测试、方法调用)

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. #include<stdio.h>
3. #include "18-dynamicSequenceTable.h"
4. 
5. TestSEQList1()
6. {
7.  SeqList s = {NULL,0,0};
8. 
9.  //想要修改结构体变量,必须传结构体的地址
10.   //因此SeqListInit的实参是结构体地址,形参应该是指针,用来接收结构体地址,其他方法同理
11.   SeqListInit(&s);
12. 
13.   //尾插 1 2 3 4 5
14.   SeqListPushBack(&s, 1);
15.   SeqListPushBack(&s, 2);
16.   SeqListPushBack(&s, 3);
17.   SeqListPushBack(&s, 4);
18.   SeqListPushBack(&s, 5);
19. 
20.   //头插 0 0 0 0 0
21.   SeqListPushFront(&s, 0);
22.   SeqListPushFront(&s, 0);
23.   SeqListPushFront(&s, 0);
24.   SeqListPushFront(&s, 0);
25.   SeqListPushFront(&s, 0);
26.   SeqListPrint(&s);
27. 
28.   //头删一个元素
29.   SeqListPopFront(&s);
30.   SeqListPrint(&s);
31. 
32.   //尾删一个元素
33.   SeqListPopBack(&s);
34.   SeqListPrint(&s);
35. 
36.   //指定位置插入一个元素
37.   SeqListInsert(&s,2,6);
38.   SeqListPrint(&s);
39. 
40.   //指定位置删除一个元素
41.   SeqListErase(&s, 2);
42.   SeqListPrint(&s);
43. 
44.     //修改指定位置元素
45.   SeqListModify(&s, 0, -1);
46.   SeqListPrint(&s);
47. 
48.   //销毁顺序表
49.   SeqListDestroy(&s);
50. 
51. }
52. 
53. int main()
54. {
55.   TestSEQList1();
56.   return 0;
57. }

执行结果:


相关文章
|
14天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
90 9
|
13天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
56 16
|
13天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
62 8
|
16天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
44 4
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
17天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
49 3
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
16天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
37 0
|
存储 缓存 C语言
数据结构——双链表(C语言)
数据结构——双链表(C语言)
|
5月前
|
存储
数据结构——双向链表(C语言版)
数据结构——双向链表(C语言版)
31 2

热门文章

最新文章