当前位置:   article > 正文

(一)(C语言)实现顺序表(静态分配)的基本操作(初始化、判断是否为空,打印表,插入和删除等)讲解(含相关C语言代码讲解及运行结果)_顺序表初始化

顺序表初始化

(一)(C语言)实现顺序表(静态分配)的基本操作(初始化、查找、打印表、插入和删除等)讲解(含C语言完整代码讲解及运行结果)

文章目录

  • 一、顺序表
  • 二、顺序表相关操作
    • 1.初始化
    • 2.插入
    • 3.删除
    • 4.打印表
    • 5.查找
  • 三、完整代码讲解(C语言)
  • 总结

一、顺序表

       线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。因此,顺序表的特点是表中元素的逻辑顺序和其物理顺序相同。

1.顺序表(静态分配)

  1. #define Maxsize 10 //定义线性表的最大长度
  2. typedef struct
  3. {
  4. ElemType data[MaxSize]; //顺序表的元素(Elemtype为元素的类型,可替换为int,char,float等)
  5. int length; //顺序表的当前长度(表中元素个数)
  6. }SqList; //顺序表的类型定义

       一维数组可以静态分配,也可以动态分配。在静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据就会溢出,进而导致程序崩溃。

2.顺序表(动态分配) 

  1. #define InitSize 100 //表长度的初始定义
  2. typedef struct
  3. {
  4. int *data; //指示动态分配数组的指针,这里的int可替换为其他类型
  5. int length; //数组的当前个数
  6. int MaxSize; //数组的最大容量
  7. }SeqList; //动态分配数组顺序表的类型定义
  8. //C语言的初始动态分配语句:
  9. L.data=(ElemType *)malloc(sizeof(ElemType)*InitSize);//动态申请一整片的内存空间
  10. //初始化为
  11. void InitList(SeqList *L){
  12. (*L).data=(int*)malloc(InitSize*sizeof(int));//这里的int可替换为其他类型
  13. (*L).length=0;
  14. (*L).MaxSize=InitSize;
  15. }

       在动态分配时,存储数组的空间在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用于替换原来的存储空间,从而达到扩充存储数组空间的目的,不需要为线性表一次性地划分所有空间。

       注:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时动态决定。

二、顺序表相关操作(静态分配)

1.初始化

代码如下(示例):

  1. //初始化
  2. bool InitList(SqList *L){
  3. for (int i = 0; i < MaxSize; i++)
  4. {
  5. (*L).data[i]=0; //利用循环将表中的数据都为0
  6. }
  7. (*L).length=0; //将length也置为0,意思是当前表中无数据
  8. return true;
  9. }

2.插入

由于在位序为i的位置,增加一个元素,则原来位序为i及位序i之后的元素都要往后移一位,将位序i给空出来,用来存放要插入的新元素。例:位序i后一位为i+1,位序i的要往后移一位,就是将位序i处的值放在位序为i+1处,因为数组中下标从0开始的,则在数组中表现为data[i]=data[i-1];

  1. // 插入
  2. bool ListInsert(SqList *L,int i,int e){
  3. if(i<1||i>(*L).length+1){
  4. printf("要插入的位置错误\n"); //只能在表中第一个元素和(最后一个元素的后一位)两者之间插入,
  5. return false; //按位序的话,i的值要满足1<=i<=length+1
  6. }
  7. if((*L).length>=MaxSize) {
  8. printf("存储空间已满!\n"); //如果length大于等于Maxsize说明表已满,插入数据失败
  9. return false;
  10. }
  11. int j;
  12. for ( j=(*L).length; j>=i; j--) //从最后一位开始到第i位(包括第i位),从后往前,
  13. { //将值往后移一位,从而将第i位给空出来(这里的i都为位序,从1开始)
  14. (*L).data[j]=(*L).data[j-1];
  15. }
  16. (*L).data[i-1]=e; //将要插入的值放入位序为i中,即在数组中为data[i-1]
  17. (*L).length++; //由于表插入了一个元素,故length的值要加1
  18. return true;
  19. }

3.删除

由于删除了一个元素,表中会空出来一个位置,即位序i会空出来,这时候就需要将位序i之后的值往前移一位 ,例:位序i后一位为i+1,要往前移一位,就是将位序i+1处的值放在位序为i处,因为数组中下标从0开始的,则在数组中表现为data[i-1]=data[i];

  1. // 删除
  2. bool ListDelete(SqList *L,int i,int *e){
  3. if(i<1||i>(*L).length){
  4. printf("要删除的位置错误\n"); //判断i值是否合法
  5. return false;
  6. }
  7. (*e)=(*L).data[i-1]; //将位序i中的值赋予e,用于返回
  8. int j;
  9. for (j=i;j<(*L).length;j++) //利用循环从位序为i处到位序为的length最后一个元素,从前往后依次往前移动一个元素
  10. {
  11. (*L).data[j-1]=(*L).data[j];
  12. }
  13. (*L).length--; //由于删除一个元素,所以length减一
  14. return true;
  15. }

4.打印表

  1. //打印表
  2. void printList(SqList L){
  3. for (int i = 0; i < L.length; i++) //i值从0开始
  4. {
  5. printf("第%d的值为:%d\n",i+1,L.data[i]); //利用数组下标依次将表中数据元素打印出来
  6. }
  7. if(L.length==0){
  8. printf("表中没有数据!\n"); //length为0时,此时表中无数据元素
  9. }
  10. }

5.查找(按位查找和按值查找)

  1. //查找
  2. //1.按位查找
  3. bool GetElem(SqList L,int i){
  4. if (i<1||i>L.length)
  5. {
  6. printf("要查询的值的位置不合法!\n");
  7. return false; //如果i值不合法(i只能在1<=i<=length内),则查找失败
  8. }
  9. printf("表中第%d个元素为:%d\n",i,L.data[i-1]);//输出表中位序为i的值
  10. return true;
  11. }
  12. //2.按值查找
  13. bool LocateElem(SqList L,int e){
  14. if (L.length==0)
  15. {
  16. return false;
  17. }
  18. for (int i = 0; i < L.length; i++)//利用循环依次查找表中数据元素
  19. {
  20. if (L.data[i]==e) //并依次和要查找的e值进行比较,如果相同则在表中找到e值,输出
  21. {
  22. printf("此值%d为表中第%d个元素\n",e,i+1);
  23. return true;
  24. }
  25. }
  26. }

三、完整代码讲解(C语言) 

在主函数中,为了方便我就设计插入了两个值,然后依次打印表中数据,按位查找,按值查找,删除,打印表进行。

  1. #include<stdio.h>
  2. #include<stdbool.h> //如果要用bool类型,要加上这个头文件
  3. #include<stdlib.h>
  4. // 顺序表(静态分配)
  5. #define MaxSize 10
  6. typedef struct
  7. {
  8. int data[MaxSize];
  9. int length;
  10. }SqList;
  11. //初始化
  12. bool InitList(SqList *L){
  13. for (int i = 0; i < MaxSize; i++)
  14. {
  15. (*L).data[i]=0; //利用循环将表中的数据都为0
  16. }
  17. (*L).length=0; //将length也置为0,意思是表中无数据
  18. return true;
  19. }
  20. // 判断顺序表是否为空
  21. int IsEmpty(SqList L){
  22. if (L.length==0)
  23. {
  24. return 111;
  25. }
  26. else
  27. {
  28. return 000;
  29. }
  30. }
  31. //打印表
  32. void printList(SqList L){
  33. for (int i = 0; i < L.length; i++) //i值从0开始
  34. {
  35. printf("第%d的值为:%d\n",i+1,L.data[i]); //利用数组下标依次将表中数据元素打印出来
  36. }
  37. if(L.length==0){
  38. printf("表中没有数据!\n"); //length为0时,此时表中无数据元素
  39. }
  40. }
  41. // 插入
  42. bool ListInsert(SqList *L,int i,int e){
  43. if(i<1||i>(*L).length+1){
  44. printf("要插入的位置错误\n"); //只能在表中第一个元素和(最后一个元素的后一位)两者之间插入,
  45. return false; //按位序的话,1<=i<=length+1
  46. }
  47. if((*L).length>=MaxSize) {
  48. printf("存储空间已满!\n"); //如果length大于等于Maxsize说明表已满,插入数据失败
  49. return false;
  50. }
  51. int j;
  52. for ( j=(*L).length; j>=i; j--) //从最后一位开始到第i位(包括第i位),从后往前,
  53. { //将值往后移一位,从而将第i位给空出来(这里的i都为位序,从1开始)
  54. (*L).data[j]=(*L).data[j-1];
  55. }
  56. (*L).data[i-1]=e; //将要插入的值放入位序为i中,即在数组中为data[i-1]
  57. (*L).length++; //由于表插入了一个元素,故length的值要加1
  58. return true;
  59. }
  60. // 删除
  61. bool ListDelete(SqList *L,int i,int *e){
  62. if(i<1||i>(*L).length){
  63. printf("要删除的位置错误\n"); //判断i值是否合法
  64. return false;
  65. }
  66. (*e)=(*L).data[i-1]; //将位序i中的值赋予e,用于返回
  67. int j;
  68. for (j=i;j<(*L).length;j++) //利用循环从位序为i处到位序为的length最后一个元素,从前往后依次往前移动一个元素
  69. {
  70. (*L).data[j-1]=(*L).data[j];
  71. }
  72. (*L).length--; //由于删除一个元素,所以length减一
  73. return true;
  74. }
  75. //查找
  76. //1.按位查找
  77. bool GetElem(SqList L,int i){
  78. if (i<1||i>L.length)
  79. {
  80. printf("要查询的值的位置不合法!\n");
  81. return false; //如果i值不合法(i只能在1<=i<=length内),则查找失败
  82. }
  83. printf("表中第%d个元素为:%d\n",i,L.data[i-1]);//输出表中位序为i的值
  84. return true;
  85. }
  86. //2.按值查找
  87. bool LocateElem(SqList L,int e){
  88. if (L.length==0)
  89. {
  90. return false;
  91. }
  92. for (int i = 0; i < L.length; i++)//利用循环依次查找表中数据元素
  93. {
  94. if (L.data[i]==e) //并依次和要查找的e值进行比较,如果相同则在表中找到e值,输出
  95. {
  96. printf("此值%d为表中第%d个元素\n",e,i+1);
  97. return true;
  98. }
  99. }
  100. }
  101. int main(){
  102. SqList L;
  103. // 初始化
  104. InitList(&L);
  105. // 判断是否为空
  106. int ret; //用来接收判断表是否为空的数据
  107. ret=IsEmpty(L);
  108. printf("ret= %d\n",ret); //表为空输出“111”,表不为空输出“000”
  109. // 第一次插入数据
  110. printf("输入要插入的位置:\n");
  111. int i;int e;
  112. scanf("%d",&i); //输入要插入的位置
  113. printf("输入要插入的值:\n");
  114. scanf("%d",&e); //输入插入的值
  115. ListInsert(&L,i,e);
  116. // 打印表
  117. printList(L);
  118. //第二次插入数据
  119. printf("输入要插入的位置:\n");
  120. scanf("%d",&i);
  121. printf("输入要插入的值:\n");
  122. scanf("%d",&e);
  123. ListInsert(&L,i,e);
  124. // 再次打印表
  125. printList(L);
  126. //按位查找
  127. printf("输入要查询第几位的值:\n");
  128. scanf("%d",&i);
  129. GetElem(L,i);
  130. //按值查找
  131. printf("输入要查询的值:\n");
  132. scanf("%d",&e);
  133. LocateElem(L,e);
  134. // 删除数据
  135. printf("输入要删除的位置:\n");
  136. int n;int e3; //e3用来接收删除所返回的要删除的值
  137. scanf("%d",&n); //输入要删除第几个值
  138. ListDelete(&L,n,&e3);
  139. printf("删除的值为:%d\n",e3); //输出e3
  140. // 打印表
  141. printList(L);
  142. system("pause");
  143. }

结果如下: 


总结

顺序表的优点:

            1.存储密度大:每个存储结点只存储数据本身

            2.可以随机存取表中任一元素

顺序表的缺点:

            1.在插入、删除某一元素时,需要移动大量元素

            2.大片连续空间分配不方便

            3.改变容量不方便


文章还有瑕疵,请各位指正。

链表的操作和链表的一些不易理解的知识会在下一篇介绍,如:LNode *和LinkList的区别,和在C语言中如何实现链表的操作。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/460644
推荐阅读
相关标签
  

闽ICP备14008679号