当前位置:   article > 正文

实验1.顺序表操作和单链表操作_数据结构实验报告-实验一 顺序表、单链表基本操作的实现

数据结构实验报告-实验一 顺序表、单链表基本操作的实现

一、实验目的

1.掌握线性表的存储结构及相关的操作;

2.熟悉对顺序表、单链表的一些基本操作,如初始化、插入、删除等;

3.用C语言编制程序,程序中写出详细注释;

4.给出测试结果,验证程序的正确性。

二、实验要求

1、程序要求包含头文件以及main函数

2、实验中所设计的函数(算法)需要满足实验的要求

3、程序的编译、运行要成功通过

4、运行的结果正确,且有相应的提示

三、实验环境

WIND7、VC++6.0或C与C++程序设计学习与实验系统

四、实验内容

1.插入元素操作:将新元素x从尾部插入顺序表a中、将新元素x插入到顺序表a中第i个位置、将新元素x插入到递增有序的顺序表a中适当的位置。

2.删除元素运算:删除顺序表a中第i个元素、删除顺序表a中值相同的多余元素。

3.创建一个带头结点的单链表

4.插入元素操作:将新元素x插入到单链表head的头部、将新元素x插入到单链表head的尾部、将新元素x插入到单链表head中第i个元素之后。

5.删除元素运算:删除单链表head中值为x的元素。

五、源代码及算法分析

1.插入元素操作:将新元素x从尾部插入顺序表a中、将新元素x插入到顺序表a中第i个位置、将新元素x插入到递增有序的顺序表a中适当的位置。

  1. // 求表长操作
  2. int getlen (sqlist * L) {
  3. return(L -> length);
  4. }
  5. // 插入操作
  6. int insert (sqlist * L, int i, ElemType x) {
  7. int j;
  8. if (i < 1 || i > L -> length+1) return 0; /* 参数i不合理,返回0 */
  9. if (L -> length == L -> listsize) { /* 存储空间不够,增加一个存储空间 */
  10. L -> data = (ElemType * )realloc(L -> data, (L -> listsize+1) * sizeof(ElemType));
  11. L -> listsize++; /* 重置存储空间长度 */
  12. }
  13. for (j = L -> length-1; j >= i-1; j--)
  14. L -> data[j+1] = L -> data[j]; /* 将序号为i及之后的数据元素后移一位 */
  15. L -> data[i-1] = x; /* 在序号i处放入x */
  16. L -> length++; /* 顺序表长度增1 */
  17. return 1; /* 插入成功,返回1 */
  18. }
  19. // 将新元素x插入到递增有序的顺序表a中适当的位置
  20. int compare(sqlist * L, ElemType x) {
  21. for(int i = 0; i <= getlen(L); i++) {
  22. if(x <= L->data[i]) { // 如果x<=某个元素,则x放在该元素的位置上
  23. insert(L, i+1, x);
  24. break;
  25. }
  26. else { // 如果x比所有元素都大,则x放在顺序表的末尾
  27. insert(L, getlen(L)+1, x);
  28. break;
  29. }
  30. }
  31. }

算法分析:插入操作主要用到了getlen(sqlist * L)、insert(sqlist * L, int i, ElemType x)和compare(sqlist * L, ElemType x)方法。①getlen()方法主要是返回表长的长度。

②insert()方法主要实现了将新元素x插入到顺序表lists中第i个位置。首先,该方法的形参有顺序表的指针,整型变量i和顺序表的新元素x。然后在方法体内首先通过第一个if判断语句,判断参数i是否合理,如果参数i不合理,返回0;接着通过第二个if判断语句判断顺序表长度与当前存储空间是否相等,不等则通过realloc()方法增加一个存储空间并重置存储空间长度。再接着通过for循环将序号为i及之后的数据元素后移一位,在序号i处放入x,顺序表长度增1,插入成功,返回1。

③compare()方法主要实现了将新元素x插入到递增有序的顺序表a中适当的位置。首先运用for循环将新输入的元素x与顺序表中原有的元素从下标索引为0开始比较,如果x<=某个元素,则将该元素的下标i+1,调用insert()方法,把x放在适当位置;如果x>所有元素,x放在顺序表的末尾,则直接调用insert()方法,第二个参数输入getlen()方法返回的值+1。

最后就是在main()方法里调用上述方法即可。

2.删除元素运算:删除顺序表a中第i个元素、删除顺序表a中值相同的多余元素。

  1. // 删除操作
  2. int deletes(sqlist * L, int i, ElemType * e) {
  3. int j;
  4. if (i < 1 || i > L->length) return 0; /* 参数i不合理,返回0 */
  5. *e = L -> data[i-1]; /* 存储被删除的元素 */
  6. for (j = i; j < L->length; j++) {
  7. L -> data[j-1] = L -> data[j]; /* 将序号为i及之后的数据元素前移一位 */
  8. }
  9. L->length--; /* 顺序表长度减1 */
  10. return 1; /* 删除成功,返回1 */
  11. }
  12. // 删除顺序表a中值相同的多余元素
  13. void delete_r(sqlist *L) {
  14. int count;
  15. int k;
  16. for(int i = 0;i<L->length;i++) {
  17. k = i+1;
  18. count = 0;
  19. for(int j = i+1; j<L->length; j++) {
  20. if(L->data[i]!=L->data[j]) {
  21. L->data[k++] = L->data[j];
  22. }
  23. else {
  24. count++;
  25. }
  26. }
  27. L->length-=count;
  28. }
  29. }

        算法分析:删除元素运算主要用到deletes(sqlist * L, int i, ElemType * e)和delete_r(sqlist *L)两个方法。

  • deletes()方法主要是删除顺序表a中第i个元素。deletes()方法的形参是顺序表的地址,整型变量i和ElemType类型的e指针。在该方法里,首先用if判断传入的参数i是否合理,若不合理则返回0。然后用*e存储被删除的元素,接着开始用for循环将序号为i及之后的数据元素前移一位,也就是覆盖要删除的元素:首先for循环里的条件是j赋值为用户输入的i,接着如果j小于顺序表的长度,就进行+1操作。然后就通过下标索引把下标为j-1的元素赋值为下标为j的元素值,以此类推。
  • delete_r()方法主要是删除顺序表a中值相同的多余元素。先定义两个整型变量count和k。利用这两个变量作为索引下标,把相同的元素用后一位元素覆盖掉原来的值。

3.创建一个带头结点的单链表

  1. // 创建一个带头结点的单链表
  2. slink * creslink(int n)
  3. {
  4. slink * head, * p, * s; // p用于指向新链入节点,s用于指向新开辟节点
  5. int i;
  6. p = head = (slink *)malloc(sizeof(slink)); // 创建头节点
  7. for(i = 1; i <= n; i++) {
  8. s = (slink *)malloc(sizeof(slink)); // s指向新开辟节点
  9. printf("请输入元素:");
  10. scanf("%d", &s -> data); // 新节点数据域赋值
  11. p -> next = s; // 将新节点连接到p所指节点的后面
  12. p = s; // p指向新链入节点
  13. }
  14. p -> next = NULL; // 尾节点的指针域置为空
  15. return head; // 返回头指针
  16. }

算法分析:p用于指向新链入节点并用malloc()函数返回内存地址值,s用于指向新开辟节点同样用malloc()函数返回内存地址值,s指向新开辟节点,将新节点连接到p所指节点的后面 ,p指向新链入节点 ,最后把尾节点的指针域置为空,返回头指针。

4.插入元素操作:将新元素x插入到单链表head的头部、将新元素x插入到单链表head的尾部、将新元素x插入到单链表head中第i个元素之后

  1. // 插入元素操作
  2. int insert(slink * head, int i, ElemType x) {
  3. slink * p, * q;
  4. int j;
  5. if(i < 1) return 0; // 参数i不合理,返回0
  6. p = head;
  7. j = 0;
  8. while(p != NULL && j<i-1) {
  9. p = p -> next; // 从第一个节点开始查找第i-1个节点,由p指向它
  10. j++;
  11. }
  12. if(p == NULL) return 0; // 参数i值超过链表长度+1,返回0
  13. q = (slink *)malloc(sizeof(slink));
  14. q -> data = x; // 创建值为x的节点q
  15. q -> next = p -> next; // 将q指向的节点插到p指向的节点之后
  16. p -> next = q;
  17. return 1; // 插入成功,返回1
  18. }

算法分析:首先使用if判断语句判断参数i是否合理,若不合理则返回0;然后再使用while循环从第一个节点开始查找第i-1个节点,由p指向它;再使用if判断语句判断p是否等于NULL,若等于NULL,则链表长度+1,返回0;最后创建值为x的节点q,将q指向的节点插到p指向的节点之后。

5.删除元素运算:删除单链表head中值为x的元素。

  1. // 删除元素运算
  2. int deletes(slink * head, int i, ElemType * e) {
  3. slink * p, * q;
  4. int j;
  5. if(i < 1) return 0;
  6. p = head;
  7. j = 0;
  8. while(p -> next != NULL && j<i-1) {
  9. p = p -> next;
  10. j++;
  11. }
  12. if(p -> next == NULL) return 0;
  13. q = p -> next;
  14. p -> next = q -> next;
  15. * e = q -> data;
  16. free(q);
  17. return 1;
  18. }

算法分析:首先使用if判断语句判断参数i是否合理,若不合理则返回0;接着使用while循环从第1个节点开始查找第i-1个节点,由p指向它;再使用if判断语句判断p->next是否等于NULL,若等于NULL,则参数i值超过链表的长度并且返回0;接着p指向第i个节点,p的指针域指向q指向节点的下一个节点,删除第i个节点。

六、运行测试(对实验结果进行相应分析,或总结实验的心得体会,并提出算法的改进意见)

1.插入元素操作:将新元素x从尾部插入顺序表a中、将新元素x插入到顺序表a中第i个位置、将新元素x插入到递增有序的顺序表a中适当的位置。

2.删除元素运算:删除顺序表a中第i个元素、删除顺序表a中值相同的多余元素。

1和2的运行结果如下图:

由图知,1和2的要求均已完成且通过测试。

3.创建一个带头结点的单链表

4.插入元素操作:将新元素x插入到单链表head的头部、将新元素x插入到单链表head的尾部、将新元素x插入到单链表head中第i个元素之后。

5.删除元素运算:删除单链表head中值为x的元素。

3、4和5的运行结果如下图:

由图知,3、4和5的要求均已完成且通过测试。

七、完整代码

1.顺序表

  1. # include <stdio.h>
  2. # include <malloc.h>
  3. # define INITSIZE 100 /* 顺序表存储空间的初始分配量 */
  4. typedef int ElemType; /* 在实际问题中,根据需要定义所需的数据类型 */
  5. typedef struct {
  6. ElemType *data; /* 存储空间基地址 */
  7. int length; /* 顺序表长度(即已存入的元素个数) */
  8. int listsize; /* 当前存储空间容量(即能存入的元素个数) */
  9. }sqlist;
  10. void initlist (sqlist * L) {
  11. L -> data = (ElemType * )malloc(sizeof(ElemType) * INITSIZE);
  12. L -> length = 0;
  13. L -> listsize = INITSIZE;
  14. }
  15. // 求表长操作
  16. int getlen (sqlist * L) {
  17. return(L -> length);
  18. }
  19. // 插入操作
  20. int insert (sqlist * L, int i, ElemType x) {
  21. int j;
  22. if (i < 1 || i > L -> length+1) return 0; /* 参数i不合理,返回0 */
  23. if (L -> length == L -> listsize) { /* 存储空间不够,增加一个存储空间 */
  24. L -> data = (ElemType * )realloc(L -> data, (L -> listsize+1) * sizeof(ElemType));
  25. L -> listsize++; /* 重置存储空间长度 */
  26. }
  27. for (j = L -> length-1; j >= i-1; j--)
  28. L -> data[j+1] = L -> data[j]; /* 将序号为i及之后的数据元素后移一位 */
  29. L -> data[i-1] = x; /* 在序号i处放入x */
  30. L -> length++; /* 顺序表长度增1 */
  31. return 1; /* 插入成功,返回1 */
  32. }
  33. // 将新元素x插入到递增有序的顺序表a中适当的位置
  34. int compare(sqlist * L, ElemType x) {
  35. for(int i = 0; i <= getlen(L); i++) {
  36. if(x <= L->data[i]) { // 如果x<=某个元素,则x放在该元素的位置上
  37. insert(L, i+1, x);
  38. break;
  39. }
  40. else { // 如果x比所有元素都大,则x放在顺序表的末尾
  41. insert(L, getlen(L)+1, x);
  42. break;
  43. }
  44. }
  45. }
  46. // 删除操作
  47. int deletes(sqlist * L, int i, ElemType * e) {
  48. int j;
  49. if (i < 1 || i > L->length) return 0; /* 参数i不合理,返回0 */
  50. *e = L -> data[i-1]; /* 存储被删除的元素 */
  51. for (j = i; j < L->length; j++) {
  52. L -> data[j-1] = L -> data[j]; /* 将序号为i及之后的数据元素前移一位 */
  53. }
  54. L->length--; /* 顺序表长度减1 */
  55. return 1; /* 删除成功,返回1 */
  56. }
  57. // 删除顺序表a中值相同的多余元素
  58. void delete_r(sqlist *L) {
  59. int count;
  60. int k;
  61. for(int i = 0;i<L->length;i++) {
  62. k = i+1;
  63. count = 0;
  64. for(int j = i+1; j<L->length; j++) {
  65. if(L->data[i]!=L->data[j]) {
  66. L->data[k++] = L->data[j];
  67. }
  68. else {
  69. count++;
  70. }
  71. }
  72. L->length-=count;
  73. }
  74. }
  75. // 输出操作
  76. void list (sqlist * L) {
  77. int i;
  78. for (i = 0; i < L -> length; i++)
  79. printf("%5d", L -> data[i]);
  80. printf("\n");
  81. }
  82. int main() {
  83. ElemType a;
  84. ElemType e;
  85. sqlist lists;
  86. initlist(&lists);
  87. printf("input datas(-1 : end):");
  88. scanf("%d", &a);
  89. while(a != -1) {
  90. insert(&lists, lists.length+1, a);
  91. scanf("%d", &a);
  92. }
  93. // 将新元素x从尾部插入顺序表lists中
  94. printf("请输入新元素x:");
  95. ElemType x;
  96. scanf("%d", &x);
  97. insert(&lists, getlen(&lists)+1, x);
  98. printf("新元素x从尾部插入顺序表后的结果是:\n");
  99. list(&lists);
  100. // 将新元素x插入到顺序表lists中第i个位置
  101. printf("请输入新元素y:");
  102. ElemType y;
  103. scanf("%d", &y);
  104. printf("请输入你要插入的位置:");
  105. int location;
  106. scanf("%d", &location);
  107. insert(&lists, location, y);
  108. printf("元素插入到第%d位后的结果是:\n", location);
  109. list(&lists);
  110. // 将新元素z插入到递增有序的顺序表a中适当的位置中
  111. sqlist nlists;
  112. initlist(&nlists); // 创建一个新的空顺序表
  113. printf("请输入递增有序的顺序表(-1 : end):");
  114. ElemType datas;
  115. scanf("%d", &datas);
  116. while(datas != -1) {
  117. insert(&nlists, nlists.length+1, datas);
  118. scanf("%d", &datas);
  119. }
  120. printf("请输入新元素z:");
  121. ElemType z;
  122. scanf("%d", &z);
  123. compare(&nlists, z);
  124. printf("将新元素z插入到递增有序的顺序表a中适当的位置后的结果是:");
  125. list(&nlists);
  126. // 删除顺序表a中第i个元素
  127. printf("请输入你要删除nlists顺序表中第i个元素:");
  128. int removes;
  129. ElemType t;
  130. scanf("%d", &removes);
  131. deletes(&nlists, removes, &t);
  132. printf("删除元素后的顺序表结果为:\n");
  133. list(&nlists);
  134. // 删除顺序表a中值相同的多余元素
  135. delete_r(&nlists);
  136. printf("删除顺序表a中值相同的多余元素后的结果是:");
  137. list(&nlists);
  138. }

2.单向链表

  1. # include <stdio.h>
  2. # include <malloc.h>
  3. typedef int ElemType;
  4. typedef struct node
  5. {
  6. ElemType data; // 数据域
  7. struct node * next; // 指针域
  8. } slink;
  9. // 创建一个带头结点的单链表
  10. slink * creslink(int n)
  11. {
  12. slink * head, * p, * s; // p用于指向新链入节点,s用于指向新开辟节点
  13. int i;
  14. p = head = (slink *)malloc(sizeof(slink)); // 创建头节点
  15. for(i = 1; i <= n; i++) {
  16. s = (slink *)malloc(sizeof(slink)); // s指向新开辟节点
  17. printf("请输入元素:");
  18. scanf("%d", &s -> data); // 新节点数据域赋值
  19. p -> next = s; // 将新节点连接到p所指节点的后面
  20. p = s; // p指向新链入节点
  21. }
  22. p -> next = NULL; // 尾节点的指针域置为空
  23. return head; // 返回头指针
  24. }
  25. // 插入元素操作
  26. int insert(slink * head, int i, ElemType x) {
  27. slink * p, * q;
  28. int j;
  29. if(i < 1) return 0; // 参数i不合理,返回0
  30. p = head;
  31. j = 0;
  32. while(p != NULL && j<i-1) {
  33. p = p -> next; // 从第一个节点开始查找第i-1个节点,由p指向它
  34. j++;
  35. }
  36. if(p == NULL) return 0; // 参数i值超过链表长度+1,返回0
  37. q = (slink *)malloc(sizeof(slink));
  38. q -> data = x; // 创建值为x的节点q
  39. q -> next = p -> next; // 将q指向的节点插到p指向的节点之后
  40. p -> next = q;
  41. return 1; // 插入成功,返回1
  42. }
  43. // 删除元素运算
  44. int deletes(slink * head, int i, ElemType * e) {
  45. slink * p, * q;
  46. int j;
  47. if(i < 1) return 0;
  48. p = head;
  49. j = 0;
  50. while(p -> next != NULL && j<i-1) {
  51. p = p -> next;
  52. j++;
  53. }
  54. if(p -> next == NULL) return 0;
  55. q = p -> next;
  56. p -> next = q -> next;
  57. * e = q -> data;
  58. free(q);
  59. return 1;
  60. }
  61. // 输出操作
  62. void list(slink * head) {
  63. slink * p;
  64. p = head -> next;
  65. while(p != NULL) {
  66. printf("%4d", p -> data);
  67. p = p -> next;
  68. }
  69. printf("\n");
  70. }
  71. int main() {
  72. // 创建一个带头结点的单链表
  73. slink * links;
  74. printf("请输入你要存储的元素个数:\n");
  75. int n;
  76. scanf("%d", &n);
  77. links = creslink(n);
  78. printf("链表存储完元素后的结果是:\n");
  79. list(links);
  80. // 将新元素x插入到单链表head的头部
  81. ElemType x;
  82. printf("请输入插入链表头部的元素:");
  83. scanf("%d", &x);
  84. insert(links, 1, x);
  85. printf("元素插入到头部后的结果为:");
  86. list(links);
  87. // 将新元素x插入到单链表head的尾部
  88. printf("请输入插入链表尾部的元素:");
  89. scanf("%d", &x);
  90. insert(links, n+2, x);
  91. printf("元素插入到尾部后的结果为:");
  92. list(links);
  93. // 将新元素x插入到单链表head中第i个元素之后
  94. printf("请输入插入链表i位置的元素:");
  95. scanf("%d", &x);
  96. int i;
  97. printf("请输入你要插入的i位置:");
  98. scanf("%d", &i);
  99. insert(links, i, x);
  100. printf("元素插入到链表i位置后的结果为:");
  101. list(links);
  102. // 删除单链表head中值为x的元素
  103. printf("你要删除的元素的位置是第几位:");
  104. scanf("%d", &i);
  105. ElemType e;
  106. deletes(links, i, &e);
  107. printf("删除元素后的结果是:");
  108. list(links);
  109. }

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

闽ICP备14008679号