当前位置:   article > 正文

数据结构入门(一)顺序表的实现

数据结构入门(一)顺序表的实现

在学习数据结构之前,先要了解几个问题

1、什么是数据结构?

答:我们刚开始学习的时候见识的数组就是一个数据结构。数据结构是由“数据”和“结构”两词组织而来的。

数据:生活中的数据随处可见。比如简历上的个人信息,网页里的很多信息,或者是1、2、3这样的数字,手机里保存的图片视频等等,都是数据。

结构:当我们想要大量使用同一类型数据时,通过手动定义大量的独立变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将大量的数据组织在一起,结构也可以理解为组织数据的方式。

例如如果想在这样一群没有组织的羊群中找到某一只的话非常困难

但是如果是在羊圈里,那么只需要需要知道这只羊在第几号,然后就可以找到它了。

数据结构:数据结构是计算机存储,组织数据的方式。数据结构是指互相之间存在一种或多种特定关系的数据元素的合集。数据结构反应数据的内部构成,即数据由哪些部分构成,以什么方式构成,以及数据元素之间呈现的结构。

总的来说,数据结构就是

  1. 能够存储数据。
  2. 存储的数据方便查找

2、我们为什么要学习数据结构?

答:如果程序中的数据不能进行有效的管理,可能会导致数据丢失,操作数据困难、野指针等情况。而通过数据结构,我们就可以很好的将数据进行管理。按照我们的方式任意对数据进行增删改查等操作。

3、学习数据结构我们需要掌握哪些知识?

答:我们至少需要掌握结构体、指针、动态内存管理的知识,才能够学习数据结构。

下面进入顺序表的学习。

一、顺序表

1、顺序表的作用

我们之所以实现顺序表,目的就是想要按照我们定义的方式,任意地去对数据进行增删查改的操作,目的在于可以更好地管理所存储的数据,比如我们手机上都有的通讯录,他就可以用顺序表来进行实现。

2、顺序表和数组的区别

顺序表的底层结构是数组,对数组的封装,实现了常用的增删查改等接口。

3、顺序表的分类

顺序表分为:静态顺序表和动态顺序表

静态顺序表:

静态顺序表就是使用的是给定长度的数组来存储数据。下面代码实现的就是静态顺序表。

  1. #define N 7
  2. typedef int SLDataList;
  3. typedef struct SeqList
  4. {
  5. SLDataList arr[N];
  6. int size;
  7. }SL;

静态顺序表是基于数组arr来实现的,并且长度为固定的7个整型。size表示arr数组里所存储的有效数据个数。将int定义为SLDataList是因为,在实际使用顺序表的时候,我们进行管理的内容可能不是int类型,有可能是char或者别的类型。这时候直接把typedef后面的int修改就好了。

缺陷:空间给少了不够用,给多了会造成空间浪费。

如果我们给定的空间不足以存放我们的数据,这可能导致数据丢失,这在工作中是非常严重的技术,所以我们一般不推荐使用静态顺序表,而是使用动态顺序表。

动态顺序表:

特点:按需申请

  1. typedef int SLDataType;
  2. typedef struct SeqList
  3. {
  4. SLDataType* arr;//储存数据的底层结构
  5. int capacity;//记录顺序表的空间大小
  6. int size;//记录顺序表当前有效的数据个数
  7. }SL;

上面就是动态顺序表,与静态顺序表一样,都是在结构体内包含所需要的变量。
代码讲解:
这里与静态顺序表相比用来存储数据的底层结构是一个整形指针arr,并且还多出来一个变量capacity,因为静态顺序表的空间大小是固定的,而动态顺序表的空间大小是可以增容扩大的,所以在动态顺序表里面也必然需要一个变量来表示空间的总大小。

4、动态顺序表的实现

1)、分装文件

对于动态顺序表的实现我们采用分装文件的方法给大家进行讲解。
在VS中创建一个新项目,打开视图,新建一个头文件SeqList.h里面完成定义顺序表的结构,顺序表要实现的接口/方法,再建两个源文件SeqList.cpp和test.cpp分别是实现文件和测试文件,在实现文件中是具体实现顺序表的方法,在测试文件中进行测试顺序表,检查是否存在BUG。

2)、定义动态顺序表

SeqList.h:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. //动态顺序表
  4. typedef int SLDataType;
  5. typedef struct SeqList
  6. {
  7. SLDataType* arr;//储存数据的底层结构
  8. int capacity;//记录顺序表的空间大小
  9. int size;//记录顺序表当前有效的数据个数
  10. }SL;

3)、初始化函数SLInit

SeqList.h:

void SLInit(SL* ps);

SeqList.cpp:

  1. void SLInit(SL* ps)
  2. {
  3. ps->arr = NULL;
  4. ps->capacity = ps->size = 0;
  5. }

4)、数据管理函数头插和尾差以及扩容函数

SeqList.cpp:

扩容函数:

  1. void SLCheckCapcity(SL* ps)
  2. {
  3. if (ps->capacity == ps->size)
  4. {
  5. ps->capacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
  6. SLDataType* ptr = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * ps->capacity);
  7. if (ptr == NULL)
  8. {
  9. perror("realloc fail!");
  10. exit;
  11. }
  12. ps->arr = ptr;
  13. }
  14. }

尾插函数:

  1. void SLPushBack(SL*ps,SLDataType x)
  2. {
  3. assert(ps);
  4. SLCheckCapcity(ps);
  5. ps->arr[ps->size] = x;
  6. ps->size++;
  7. }

头插函数

  1. void SLPushFront(SL* ps, SLDataType x)
  2. {
  3. assert(ps);
  4. SLCheckCapcity(ps);
  5. for (int i = ps->size; i >0; i++)
  6. {
  7. ps->arr[i ] = ps->arr[i-1];
  8. }
  9. ps->arr[0] = x;
  10. ps->size++;
  11. }

 SeqList.h:

  1. void SLPushBack(SL* ps, SLDataType x);
  2. void SLPushFront(SL* ps, SLDataType x);

5)、头删和为尾删

SeqList.cpp:

头删:

  1. void SLPopFront(SL*ps)
  2. {
  3. assert(ps);
  4. assert(ps->size);
  5. for (int i = 0; i < ps->size-1; i++)
  6. {
  7. ps->arr[i] = ps->arr[i + 1];
  8. }
  9. ps->size--;
  10. }

6)、指定位置插入、删除

SeqList.cpp:

指定位置插入:

  1. void SLInsert(SL* ps, int pos, SLDataType x)
  2. {
  3. assert(ps);
  4. assert(pos > 0 && pos <= ps->size);
  5. if (pos==ps->size+1)
  6. {
  7. SLCheckCapcity(ps);
  8. SLPushBack(ps, x);
  9. }
  10. else
  11. {
  12. SLCheckCapcity(ps);
  13. for (int i = ps->size; i > =pos; i--)
  14. {
  15. ps->arr[ps->size] = ps->arr[ps->size - 1];
  16. }
  17. ps->arr[pos - 1] = x;
  18. ps->size++;
  19. }
  20. }

指定位置删除

  1. void SLEraes(SL* ps,int pos)
  2. {
  3. assert(ps);
  4. assert(pos > 0 && pos < ps->size + 1);
  5. for(int i=pos;i<ps->size;i++)
  6. {
  7. ps->arr[i - 1] = ps->arr[i];
  8. }
  9. ps->size--;
  10. }

7)、查找函数

SeqList.cpp:

  1. int SLFind(SL* ps, SLDataType x)
  2. {
  3. assert(ps);
  4. for (int i = 0; i < ps->size; i++)
  5. {
  6. if (x == ps->arr[i])
  7. {
  8. return i + 1;
  9. }
  10. }
  11. return -1;
  12. }

8)、销毁函数

SeqList.cpp:

  1. void SLDestroy(SL* ps)
  2. {
  3. assert(ps);
  4. free(ps->arr);
  5. ps->arr = NULL;
  6. ps->capacity = ps->size = 0;
  7. }

二、完整代码

SeqList.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. //动态顺序表
  6. typedef int SLDataType;
  7. typedef struct SeqList
  8. {
  9. SLDataType* arr;//储存数据的底层结构
  10. int capacity;//记录顺序表的空间大小
  11. int size;//记录顺序表当前有效的数据个数
  12. }SL;
  13. void SLInit(SL* ps);
  14. void SLPushBack(SL* ps, SLDataType x);
  15. void SLPushFront(SL* ps, SLDataType x);
  16. void SLDestroy(SL* ps);
  17. int SLFind(SL* ps, SLDataType x);
  18. void SLEraes(SL* ps, int pos);
  19. void SLInsert(SL* ps, int pos, SLDataType x);
  20. void SLPopFront(SL* ps);
  21. void SLPopBack(SL* ps);

SeqList.cpp

  1. //动态顺序表
  2. #include"SeqList.h"
  3. void SLInit(SL* ps)
  4. {
  5. ps->arr = NULL;
  6. ps->capacity = ps->size = 0;
  7. }
  8. void SLCheckCapcity(SL* ps)
  9. {
  10. if (ps->capacity == ps->size)
  11. {
  12. ps->capacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
  13. SLDataType* ptr = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * ps->capacity);
  14. if (ptr == NULL)
  15. {
  16. perror("realloc fail!");
  17. exit;
  18. }
  19. ps->arr = ptr;
  20. }
  21. }
  22. void SLPushBack(SL*ps,SLDataType x)
  23. {
  24. assert(ps);
  25. SLCheckCapcity(ps);
  26. ps->arr[ps->size] = x;
  27. ps->size++;
  28. }
  29. void SLPushFront(SL* ps, SLDataType x)
  30. {
  31. assert(ps);
  32. SLCheckCapcity(ps);
  33. for (int i = ps->size; i >0; i++)
  34. {
  35. ps->arr[i ] = ps->arr[i-1];
  36. }
  37. ps->arr[0] = x;
  38. ps->size++;
  39. }
  40. void SLPopBack(SL* ps)
  41. {
  42. assert(ps);
  43. assert(ps->size);
  44. ps->size--;
  45. }
  46. void SLPopFront(SL*ps)
  47. {
  48. assert(ps);
  49. assert(ps->size);
  50. for (int i = 0; i < ps->size-1; i++)
  51. {
  52. ps->arr[i] = ps->arr[i + 1];
  53. }
  54. ps->size--;
  55. }
  56. void SLInsert(SL* ps, int pos, SLDataType x)
  57. {
  58. assert(ps);
  59. assert(pos > 0 && pos <= ps->size);
  60. if (pos==ps->size+1)
  61. {
  62. SLCheckCapcity(ps);
  63. SLPushBack(ps, x);
  64. }
  65. else
  66. {
  67. SLCheckCapcity(ps);
  68. for (int i = ps->size; i > =pos; i--)
  69. {
  70. ps->arr[ps->size] = ps->arr[ps->size - 1];
  71. }
  72. ps->arr[pos - 1] = x;
  73. ps->size++;
  74. }
  75. }
  76. void SLEraes(SL* ps,int pos)
  77. {
  78. assert(ps);
  79. assert(pos > 0 && pos < ps->size + 1);
  80. for(int i=pos;i<ps->size;i++)
  81. {
  82. ps->arr[i - 1] = ps->arr[i];
  83. }
  84. ps->size--;
  85. }
  86. int SLFind(SL* ps, SLDataType x)
  87. {
  88. assert(ps);
  89. for (int i = 0; i < ps->size; i++)
  90. {
  91. if (x == ps->arr[i])
  92. {
  93. return i + 1;
  94. }
  95. }
  96. return -1;
  97. }
  98. void SLDestroy(SL* ps)
  99. {
  100. assert(ps);
  101. free(ps->arr);
  102. ps->arr = NULL;
  103. ps->capacity = ps->size = 0;
  104. }

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

闽ICP备14008679号