当前位置:   article > 正文

数据结构之顺序表_数据结构顺序表

数据结构顺序表

目录

前言

一、顺序表的结构

二、顺序表各接口函数及实现

1、顺序表的初始化

2、顺序表的打印

3、顺序表的插入函数

①、顺序表头部插入函数

②、顺序表尾部插入函数

③、任意位置插入函数

 4、顺序表的删除函数

①、头部删除函数

②、尾部删除函数

③、任意位置删除

5、顺序表的增容

6、顺序表的查找与修改

①、查找函数

②、修改数据函数

7、顺序表的销毁

结语


前言

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

数据结构可简单分为线性结构和非线性结构;顺序表就是线性结构的一种,其在物理结构和逻辑结构上都是连续的,本文针对顺序表这一结构进行分析,通过C语言实现简单的接口函数对顺序表进行操作。

一、顺序表的结构

动态顺序表结构里包含的元素有SLDataType* a指针、整型变量size、整型变量capacity。(SLDataType指顺序表存储的数据类型)

指针用于指向动态开辟的内存空间地址,size变量用于保存已存数据的个数,capacity变量负责保存目前顺序表的容量大小。

二、顺序表各接口函数及实现

1、顺序表的初始化

函数功能:负责动态开辟内存,将开辟成功的地址传给指针a,将size置为0,capacity赋值为开辟的初始容量。

函数实现(C语言):

  1. //初始化
  2. void SeqListInit(SL *ps)
  3. {
  4. ps->a = (SLDataType)malloc(sizeof(SLDataType)* 4);//SLDataType:存储的数据类型
  5. if (ps->a == NULL)//开辟失败
  6. {
  7. printf("申请内存失败\n");
  8. exit(-1);
  9. }
  10. ps->capacity = 4;//开辟空间容量
  11. ps->size = 0;//目前有效存储数据个数
  12. }

 

2、顺序表的打印

函数功能:负责对顺序表的数据进行打印输出。

函数实现:

  1. //打印顺序表
  2. void SeqListPrint(SL *ps)
  3. {
  4. for (int i = 0; i < ps->size; i++)//size控制打印次数
  5. {
  6. printf("%d ", ps->a[i]);
  7. }
  8. printf("\n");
  9. }

 

3、顺序表的插入函数

顺序表的插入函数可分为三种,第一种为头部插入,第二种为尾部插入,第三种为从任意位置插入,下面对每种情况进行分析实现。

①、顺序表头部插入函数

函数功能:从顺序表的第一个位置插入特定数据

函数实现思路:

 函数实现代码:

  1. //头插
  2. void SeqListPushFront(SL *ps, SLDataType x)
  3. {
  4. SLCheckCapacity(&ps);//检查容量,不足则增容
  5. int end = ps->size;//控制挪动数据
  6. while (end > 0)
  7. {
  8. ps->a[end] = ps->a[end - 1];
  9. --end;
  10. }
  11. ps->a[0] = x;
  12. ps->size++;
  13. }

 

②、顺序表尾部插入函数

函数功能:从顺序表的尾部插入数据。

函数实现思路:相比头部插入,尾部插入会方便很多,只需要将数据插入,size++即可。

函数实现代码:

  1. //尾插
  2. void SeqListPushBack(SL *ps, SLDataType x)
  3. {
  4. SLCheckCapacity(ps);//检查容量,不足则增容
  5. ps->a[ps->size] = x;
  6. ps->size++;
  7. }

 

③、任意位置插入函数

函数功能:从特定位置插入数据,可通过输入控制插入的位置。

函数实现思路:

 函数实现代码:

  1. //从pos位置插入
  2. void SeqListInsert(SL *ps, int pos, SLDataType x)
  3. {
  4. assert(pos >= 0 && pos <= ps->size);//判断pos的合法性
  5. SLCheckCapacity(ps);//检查容量,不足则增容
  6. //挪动数据
  7. int end = ps->size - 1;
  8. while (end >= pos)
  9. {
  10. ps->a[end + 1] = ps->a[end];
  11. --end;
  12. }
  13. ps->a[pos] = x;
  14. ps->size++;
  15. }

 

 4、顺序表的删除函数

与插入函数一样,删除函数一样分为头部删除、尾部删除、从任意位置删除三种,实现如下。

①、头部删除函数

函数功能:从顺序表的头部删除数据。

函数实现思路:

 函数实现代码:

  1. //头删
  2. void SeqListPopFront(SL *ps)
  3. {
  4. assert(ps->size > 0);//保证有数据可删
  5. int begin = 1;
  6. while (begin < ps->size)//begin小于size时挪动数据
  7. {
  8. ps->a[begin - 1] = ps->a[begin];
  9. ++begin;
  10. }
  11. ps->size--;
  12. }

②、尾部删除函数

函数功能:从尾部删除一个数据。

函数实现思路:尾部删除不需要挪动数据,只需要将size的值进行减1操作即可。

函数实现代码:

  1. //尾删
  2. void SeqListPopBack(SL *ps)
  3. {
  4. assert(ps->size > 0);
  5. ps->size--;
  6. }

③、任意位置删除

函数功能:从特定的位置删除数据。

函数思路:

 函数实现代码:

  1. //从pos位置删除
  2. void SeqListErase(SL *ps, int pos)//pos代表需要删除的位置
  3. {
  4. assert(pos >= 0 && pos < ps->size);//保证pos的合法性
  5. int begin = pos + 1;
  6. while (begin < ps->size)
  7. {
  8. ps->a[begin - 1] = ps->a[begin];
  9. ++begin;
  10. }
  11. ps->size--;
  12. }

5、顺序表的增容

函数功能:当进行插入数据时,需要对顺序表的容量进行检查,容量不足时,通过realloc函数进行内存空间的重新申请,一般增容的大小为原先的二倍。

函数实现代码:

  1. //检查容量,容量不足则增容
  2. void SLCheckCapacity(SL *ps)
  3. {
  4. if (ps->size >= ps->capacity)
  5. {
  6. //增容
  7. ps->capacity *= 2;
  8. ps->a = (SLDataType)realloc(ps->a, sizeof(SLDataType)*ps->capacity);
  9. if (ps->a == NULL)
  10. {
  11. printf("增容失败\n");
  12. exit(-1);
  13. }
  14. }
  15. }

6、顺序表的查找与修改

①、查找函数

函数功能:对顺序表内的数据进行查找,查找成功返回下标,查找失败返回-1。

函数实现代码:

  1. //查找元素
  2. int SeqListFind(SL *ps, SLDataType x)
  3. {
  4. for (int i = 0; i < ps->size; i++)//遍历顺序表
  5. {
  6. if (ps->a[i] == x)//找到数据返回下标
  7. {
  8. return i;
  9. }
  10. }
  11. return -1;//找不到返回-1
  12. }

②、修改数据函数

函数功能:根据输入的下标找到对应数据,将其修改为对应的数据。

函数实现代码:

  1. //修改指定位置数据
  2. void SeqListAlter(SL *ps, int pos, SLDataType x)
  3. {
  4. assert(pos >= 0 && pos < ps->size);
  5. ps->a[pos] = x;
  6. }

7、顺序表的销毁

因为顺序表是动态开辟的空间,所以需要一个函数用来对顺序表进行释放。

函数实现代码:

  1. //不用时释放顺序表
  2. void SeqListDestory(SL *ps)
  3. {
  4. free(ps->a);
  5. ps->a = NULL;
  6. ps->capacity = ps->size = 0;
  7. }

三、总代码分享

头文件SeqList.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<assert.h>
  4. typedef int SLDataType;//方便修改顺序表存取的数据类型
  5. enum func//菜单时使用,提高代码的可读性
  6. {
  7. 头部插入 = 1,
  8. 头部删除,
  9. 尾部插入,
  10. 尾部删除,
  11. 任意位置插入,
  12. 任意位置删除,
  13. 查找数据,
  14. 修改数据,
  15. 打印,
  16. 销毁
  17. };
  18. //动态顺序表的结构
  19. typedef struct SeqList
  20. {
  21. SLDataType* a;//存取的数据
  22. int size;//已存的数据个数
  23. int capacity;//容量
  24. }SL;
  25. //打印顺序表
  26. void SeqListPrint(SL *ps);
  27. //初始化顺序表
  28. void SeqListInit(SL *ps);
  29. //头插头删
  30. void SeqListPushFront(SL *ps, SLDataType x);
  31. void SeqListPopFront(SL *ps);
  32. //尾插尾删
  33. void SeqListPushBack(SL *ps, SLDataType x);
  34. void SeqListPopBack(SL *ps);
  35. //任意位置插入删除
  36. void SeqListInsert(SL *ps, int pos, SLDataType x);
  37. void SeqListErase(SL *ps, int pos);
  38. //增容
  39. void SLCheckCapacity(SL *ps);
  40. //查找元素,找到返回下标,没找到返回-1
  41. int SeqListFind(SL *ps, SLDataType x);
  42. //修改指定位置的数据
  43. void SeqListAlter(SL *ps, int pos, SLDataType x);
  44. //释放内存
  45. void SeqListDestory(SL *ps);

SeqList.c

  1. #include"SeqList.h"
  2. //初始化
  3. void SeqListInit(SL *ps)
  4. {
  5. ps->a = (SLDataType)malloc(sizeof(SLDataType)* 4);//SLDataType:存储的数据类型
  6. if (ps->a == NULL)//开辟失败
  7. {
  8. printf("申请内存失败\n");
  9. exit(-1);
  10. }
  11. ps->capacity = 4;//开辟空间容量
  12. ps->size = 0;//目前有效存储数据个数
  13. }
  14. //不用时释放顺序表
  15. void SeqListDestory(SL *ps)
  16. {
  17. free(ps->a);
  18. ps->a = NULL;
  19. ps->capacity = ps->size = 0;
  20. }
  21. //检查容量,容量不足则增容
  22. void SLCheckCapacity(SL *ps)
  23. {
  24. if (ps->size >= ps->capacity)
  25. {
  26. //增容
  27. ps->capacity *= 2;
  28. ps->a = (SLDataType)realloc(ps->a, sizeof(SLDataType)*ps->capacity);
  29. if (ps->a == NULL)
  30. {
  31. printf("增容失败\n");
  32. exit(-1);
  33. }
  34. }
  35. }
  36. //打印顺序表
  37. void SeqListPrint(SL *ps)
  38. {
  39. for (int i = 0; i < ps->size; i++)//size控制打印次数
  40. {
  41. printf("%d ", ps->a[i]);
  42. }
  43. printf("\n");
  44. }
  45. //头插
  46. void SeqListPushFront(SL *ps, SLDataType x)
  47. {
  48. SLCheckCapacity(&ps);//检查容量,不足则增容
  49. int end = ps->size;//控制挪动数据
  50. while (end > 0)
  51. {
  52. ps->a[end] = ps->a[end - 1];
  53. --end;
  54. }
  55. ps->a[0] = x;
  56. ps->size++;
  57. }
  58. //头删
  59. void SeqListPopFront(SL *ps)
  60. {
  61. assert(ps->size > 0);//保证有数据可删
  62. int begin = 1;
  63. while (begin < ps->size)//begin小于size时挪动数据
  64. {
  65. ps->a[begin - 1] = ps->a[begin];
  66. ++begin;
  67. }
  68. ps->size--;
  69. }
  70. //尾插
  71. void SeqListPushBack(SL *ps, SLDataType x)
  72. {
  73. SLCheckCapacity(ps);//检查容量,不足则增容
  74. ps->a[ps->size] = x;
  75. ps->size++;
  76. }
  77. //尾删
  78. void SeqListPopBack(SL *ps)
  79. {
  80. assert(ps->size > 0);
  81. ps->size--;
  82. }
  83. //从pos位置插入
  84. void SeqListInsert(SL *ps, int pos, SLDataType x)
  85. {
  86. assert(pos >= 0 && pos <= ps->size);//判断pos的合法性
  87. SLCheckCapacity(ps);//检查容量,不足则增容
  88. //挪动数据
  89. int end = ps->size - 1;
  90. while (end >= pos)
  91. {
  92. ps->a[end + 1] = ps->a[end];
  93. --end;
  94. }
  95. ps->a[pos] = x;
  96. ps->size++;
  97. }
  98. //查找元素
  99. int SeqListFind(SL *ps, SLDataType x)
  100. {
  101. for (int i = 0; i < ps->size; i++)//遍历顺序表
  102. {
  103. if (ps->a[i] == x)//找到数据返回下标
  104. {
  105. return i;
  106. }
  107. }
  108. return -1;//找不到返回-1
  109. }
  110. //从pos位置删除
  111. void SeqListErase(SL *ps, int pos)//pos代表需要删除的位置
  112. {
  113. assert(pos >= 0 && pos < ps->size);//保证pos的合法性
  114. int begin = pos + 1;
  115. while (begin < ps->size)
  116. {
  117. ps->a[begin - 1] = ps->a[begin];
  118. ++begin;
  119. }
  120. ps->size--;
  121. }
  122. //修改指定位置数据
  123. void SeqListAlter(SL *ps, int pos, SLDataType x)
  124. {
  125. assert(pos >= 0 && pos < ps->size);
  126. ps->a[pos] = x;
  127. }

main.c(菜单只是为了使用美观,与顺序表的实现无实质影响)

  1. #include"SeqList.h"
  2. void menu()
  3. {
  4. SL s3;
  5. SeqListInit(&s3);
  6. int input = 0;
  7. int i = 0, j = 0;
  8. do
  9. {
  10. printf("*****************************************************\n");
  11. printf("************1.头部插入 2.头部删除*************\n");
  12. printf("************3.尾部插入 4.尾部删除*************\n");
  13. printf("************5.任意位置插入 6.任意位置删除*********\n");
  14. printf("************7.查找数据 8.修改数据*************\n");
  15. printf("************9.打印 10.销毁 *************\n");
  16. printf("************ 0.退出 *************\n");
  17. printf("*****************************************************\n");
  18. printf("请选择:>");
  19. scanf("%d", &input);
  20. switch (input)
  21. {
  22. case 头部插入:
  23. /*int i = 0;*/
  24. printf("请输入需要插入头部的数据:>");
  25. scanf("%d", &i);
  26. SeqListPushFront(&s3, i);
  27. printf("插入成功\n");
  28. break;
  29. case 头部删除:
  30. SeqListPopFront(&s3);
  31. printf("删除成功\n");
  32. break;
  33. case 尾部插入:
  34. /*int i = 0;*/
  35. printf("请输入需要插入尾部的数据:>");
  36. scanf("%d", &i);
  37. SeqListPushBack(&s3, i);
  38. printf("插入成功\n");
  39. break;
  40. case 尾部删除:
  41. SeqListPopBack(&s3);
  42. printf("删除成功\n");
  43. break;
  44. case 任意位置插入:
  45. /*int i = 0, j = 0;*/
  46. printf("请输入需要插入的位置与数据,以空格隔开:>");
  47. scanf("%d %d", &i, &j);
  48. SeqListInsert(&s3, i, j);
  49. printf("插入成功\n");
  50. break;
  51. case 任意位置删除:
  52. /*int i = 0;*/
  53. printf("请输入需要删除的位置:>");
  54. scanf("%d", &i);
  55. SeqListErase(&s3, i);
  56. printf("删除成功\n");
  57. break;
  58. case 查找数据:
  59. /*int i = 0, j = 0;*/
  60. printf("请输入需要查找的数据:>");
  61. scanf("%d", &i);
  62. j = SeqListFind(&s3, i);
  63. if (j != -1)
  64. {
  65. printf("找到了,下标是:%d\n", j);
  66. }
  67. else
  68. printf("暂无此数据\n");
  69. break;
  70. case 修改数据:
  71. /*int i = 0, j = 0;*/
  72. printf("请输入需要修改的数据下标及修改后的数据,以空格隔开:>");
  73. scanf("%d %d", &i,&j);
  74. SeqListAlter(&s3, i, j);
  75. printf("修改成功\n");
  76. break;
  77. case 打印:
  78. SeqListPrint(&s3);
  79. break;
  80. case 销毁:
  81. SeqListDestory(&s3);
  82. printf("销毁成功\n");
  83. break;
  84. case 0:
  85. printf("退出\n");
  86. break;
  87. default:
  88. printf("输入非法\n");
  89. break;
  90. }
  91. } while (input);
  92. }
  93. int main()
  94. {
  95. menu();
  96. return 0;
  97. }

 

结语

顺序表的基本接口函数到此就介绍完毕啦~希望此文对初学者能有所帮助,也欢迎大家指正错误!

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

闽ICP备14008679号