顺序存储线性表实现

在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。

顺序存储结构的主要优点是节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况),结点之间的逻辑关系没有占用额外的存储空间。采用这种方法时,可实现对结点的随机存取,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点。

优点:随机存取表中元素。缺点:插入和删除操作需要移动元素。

线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。

给出两种基本实现:

  1. /*
  2. 静态顺序存储线性表的基本实现
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #define LIST_INITSIZE 100
  8. #define ElemType int
  9. #define Status int
  10. #define OK 1
  11. #define ERROR 0
  12. typedef struct
  13. {
  14. ElemType elem[LIST_INITSIZE];
  15. int length;
  16. }SqList;
  17. //函数介绍
  18. Status InitList(SqList *L); //初始化
  19. Status ListInsert(SqList *L, int i,ElemType e);//插入
  20. Status ListDelete(SqList *L,int i,ElemType *e);//删除
  21. void ListPrint(SqList L);//输出打印
  22. void DisCreat(SqList A,SqList *B,SqList *C);//拆分(按正负),也可以根据需求改
  23. //虽然思想略简单,但是要写的没有错误,还是需要锻炼coding能力的
  24. Status InitList(SqList *L)
  25. {
  26. L->length = 0;//长度为0
  27. return OK;
  28. }
  29. Status ListInsert(SqList *L, int i,ElemType e)
  30. {
  31. int j;
  32. if(i<1 || i>L->length+1)
  33. return ERROR;//判断非法输入
  34. if(L->length == LIST_INITSIZE)//判满
  35. {
  36. printf("表已满");//提示
  37. return ERROR;//返回失败
  38. }
  39. for(j = L->length;j > i-1;j--)//从后往前覆盖,注意i是从1开始
  40. L->elem[j] = L->elem[j-1];
  41. L->elem[i-1] = e;//在留出的位置赋值
  42. (L->length)++;//表长加1
  43. return OK;//反回成功
  44. }
  45. Status ListDelete(SqList *L,int i,ElemType *e)
  46. {
  47. int j;
  48. if(i<1 || i>L->length)//非法输入/表空
  49. return ERROR;
  50. *e = L->elem[i-1];//为了返回值
  51. for(j = i-1;j <= L->length;j++)//从前往后覆盖
  52. L->elem[j] = L->elem[j+1];
  53. (L->length)--;//长度减1
  54. return OK;//返回删除值
  55. }
  56. void ListPrint(SqList L)
  57. {
  58. int i;
  59. for(i = 0;i < L.length;i++)
  60. printf("%d ",L.elem[i]);
  61. printf("\n");//为了美观
  62. }
  63. void DisCreat(SqList A,SqList *B,SqList *C)
  64. {
  65. int i;
  66. for(i = 0;i < A.length;i++)//依次遍历A中元素
  67. {
  68. if(A.elem[i]<0)//判断
  69. ListInsert(B,B->length+1,A.elem[i]);//直接调用插入函数实现尾插
  70. else
  71. ListInsert(C,C->length+1,A.elem[i]);
  72. }
  73. }
  74. int main(void)
  75. {
  76. //复制的
  77. SqList L;
  78. SqList B, C;
  79. int i;
  80. ElemType e;
  81. ElemType data[9] = {11,-22,33,-3,-88,21,77,0,-9};
  82. InitList(&L);
  83. InitList(&B);
  84. InitList(&C);
  85. for (i = 1; i <= 9; i++)
  86. ListInsert(&L,i,data[i-1]);
  87. printf("插入完成后L = : ");
  88. ListPrint(L);
  89. ListDelete(&L,1,&e);
  90. printf("删除第1个后L = : ");
  91. ListPrint(L);
  92. DisCreat(L , &B, &C);
  93. printf("拆分L后B = : ");
  94. ListPrint(B);
  95. printf("拆分L后C = : ");
  96. ListPrint(C);
  97. printf("拆分L后L = : ");
  98. ListPrint(L);
  99. }

静态:长度固定

动态:不够存放可以加空间(搬家)

  1. /*
  2. 子任务名任务:1_2 动态顺序存储线性表的基本实现
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #define LIST_INIT_SIZE 100
  8. #define LISTINCREMENT 10
  9. #define Status int
  10. #define OVERFLOW -1
  11. #define OK 1
  12. #define ERROR 0
  13. #define ElemType int
  14. typedef struct
  15. {
  16. ElemType * elem;
  17. int length;
  18. int listsize;
  19. }SqList;
  20. //函数介绍
  21. Status InitList(SqList *L); //初始化
  22. Status ListInsert(SqList *L, int i,ElemType e);//插入
  23. Status ListDelete(SqList *L,int i,ElemType *e);//删除
  24. void ListPrint(SqList L);//输出打印
  25. void DeleteMin(SqList *L);//删除最小
  26. Status InitList(SqList *L)
  27. {
  28. L->elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));//申请100空间
  29. if(!L->elem)//申请失败
  30. return ERROR;
  31. L->length = 0;//长度0
  32. L->listsize = LIST_INIT_SIZE;//容量100
  33. return OK;//申请成功
  34. }
  35. Status ListInsert(SqList *L,int i,ElemType e)
  36. {
  37. int j;
  38. ElemType *newbase;
  39. if(i<1 || i>L->length+1)
  40. return ERROR;//非法输入
  41. if(L->length >= L->listsize)//存满了,需要更大空间
  42. {
  43. newbase = (ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));//大10的空间
  44. if(!newbase)//申请失败
  45. return ERROR;
  46. L->elem = newbase;//调指针
  47. L->listsize+= LISTINCREMENT;//新容量
  48. }
  49. for(j=L->length;j>i-1;j--)//从后往前覆盖
  50. L->elem[j] = L->elem[j-1];
  51. L->elem[i-1] = e;//在留出的位置赋值
  52. L->length++;//长度+1
  53. return OK;
  54. }
  55. Status ListDelete(SqList *L,int i,ElemType *e)
  56. {
  57. int j;
  58. if(i<1 || i>L->length)//非法输入/表空
  59. return ERROR;
  60. *e = L->elem[i-1];//为了返回值
  61. for(j = i-1;j <= L->length;j++)//从前往后覆盖
  62. L->elem[j] = L->elem[j+1];
  63. (L->length)--;//长度减1
  64. return OK;//返回删除值
  65. }
  66. void ListPrint(SqList L)
  67. {
  68. int i;
  69. for(i=0;i<L.length;i++)
  70. printf("%d ",L.elem[i]);
  71. printf("\n");//为了美观
  72. }
  73. void DeleteMin(SqList *L)
  74. {
  75. //表空在Listdelete函数里判断
  76. int i;
  77. int j=0;//最小值下标
  78. ElemType *e;
  79. for(i=0;i<L->length;i++)//寻找最小
  80. {
  81. if(L->elem[i] < L->elem[j])
  82. j=i;
  83. }
  84. ListDelete(L,j+1,&e);//调用删除,注意j要+1
  85. }
  86. int main(void)
  87. {
  88. SqList L;
  89. int i;
  90. ElemType e;
  91. ElemType data[9] = {11,-22,-33,3,-88,21,77,0,-9};
  92. InitList(&L);
  93. for (i = 1; i <= 9; i++)
  94. {
  95. ListInsert(&L,i,data[i-1]);
  96. }
  97. printf("插入完成后 L = : ");
  98. ListPrint(L);
  99. ListDelete(&L, 2, &e);
  100. printf("删除第 2 个后L = : ");
  101. ListPrint(L);
  102. DeleteMin(&L);
  103. printf("删除L中最小值后L = : ");
  104. ListPrint(L);
  105. DeleteMin(&L);
  106. printf("删除L中最小值后L = : ");
  107. ListPrint(L);
  108. DeleteMin(&L);
  109. printf("删除L中最小值后L = : ");
  110. ListPrint(L);
  111. }