本文详细的介绍了数据结构当中的最基础的顺序表,可以让初学者对顺序表进行深刻的的理解
顺序表是一种线性结构,它的逻辑上相邻的数据在计算机内的存储位置也是相邻的,可以快速定位第几个元素,中间不允许有空,所以插入、删除时需要移动大量元素。顺序表可以分配一段连续的存储空间。顺序表上的基本操作有:初始化、顺序表头插、尾插、头删、尾删、查找、插入、删除、修改、销毁顺序表。
一个程序要进行首先一个功能,首先要保证要进行初始化。对数据的初始化就如同汽车的车架子相同。
主体思想:为程序开辟所需要的内存空间,并对开辟的结构体进行初始化
顺序表的初始化,首先要保证头节点地址不为空,然后使用malloc函数开辟一个固定大小结构体的空间,使结构体的当中的指针至指向该空间,并且判断是否开辟失败,如果失败perror函数返回开辟失败的原因,并将结构体的其他的变量进行初始化
- void SLInit(SL* ps)
- {
- assert(ps);
- ps->a = (SLDataType*)malloc(sizeof(SLDataType)*4);
- if (ps->a == NULL)
- {
- perror("malloc failed");
- return;
- }
- ps->size = 0;
- ps->capacity = 4;
- }
扩容函数主要是为满足增加功能在使用时的内存不足的情况,而该函数可以帮助函数进行空间的扩大
主体思想:先判断该结构体指向的地址不为空,然后进行数据存放数量和空间大小进行比较,如果有效存储空间满了就进行空间的增补,使用realloc函数进行在原来的空间的后面开辟空间,开辟失败就返回原因,并结束程序,开辟成功就在对指针进行重新的赋值有效空间同样进行跟改。
- void SLCheckCapacity(SL* ps)
- {
- assert(ps);
- // 满了要扩容
- if (ps->size == ps->capacity)
- {
- SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDataType)));
- if (tmp == NULL)
- {
- perror("realloc failed");
- exit(-1);
- }
- ps->a = tmp;
- ps->capacity *= 2;
- }
- }
顺序表的头插的通俗理解:
就像在超市结账时一条长长的,尽然有序的买完东西人们正在排着队,突然来了一个人,以非常豪横的态度要第一个结账,大家看这个人不好惹,不想自找麻烦,就默认让这个人插了队,这个人插了队不要紧,因为他一个的插队造成第一个位置原本只能一个人的位置,现在两个人站着那里,就比较拥挤,这个时候,那个豪横的人就向后面的人说往后退一个位置,后面的人就和他后面的人说让个位置,就这样一个人的插入让整个队伍向后退了一个位置。
主体思想:判断结构体地址不为空。在判断空间是否足够,不够就扩容,然后利用数据的下标写一个循环进行数据向后移动,循环完的顺序表就可以利用下标在数组头部进行插入,再让有效数据的大小进行加一位
- void SLPushFront(SL* ps, SLDataType x)
- {
- assert(ps);
- SLCheckCapacity(ps);
- // 挪动数据
- int end = ps->size - 1;
- while (end >= 0)
- {
- ps->a[end + 1] = ps->a[end];
- --end;
- }
- ps->a[0] = x;
- ps->size++;
- }

主体思想:就数值的末端添加一个数据
先判断传的地址是否为空,在进行扩容判断,在通过下标添加数据
- void SLPushBack(SL* ps, SLDataType x)
- {
- assert(ps);
- SLCheckCapacity(ps);
- ps->a[ps->size] = x;
- ps->size++;
-
- }

主体思想:将最后一个数值释放控制权
确保传的地址和有效大小不为空,再对有效大小减少一位,这样就删除了尾数据。因为数据在空间当中的存储是比特,释放控制权就是让空间可以被其他人利用,我们不要了,不对其进行访问。
- void SLPopBack(SL* ps)
- {
- assert(ps);
- assert(ps->size > 0);
- ps->size--;
- }

主体思想:让数据此前往后的进行打印复制
- void SLPopFront(SL* ps)
- {
- assert(ps);
-
- assert(ps->size > 0);
-
- int begin = 1;
- while (begin < ps->size)
- {
- ps->a[begin - 1] = ps->a[begin];
- ++begin;
- }
-
- ps->size--;
- }

主体思想:通过下标指向的值进行判断来寻找
- int SLFind(SL* ps, SLDataType x)
- {
- assert(ps);
-
- for (int i = 0; i < ps->size; i++)
- {
- if (ps->a[i] == x)
- {
- return i;
- }
- }
- return -1;
- }

主体思想:通过查找函数找到下标,将下标及后面的数据进行移动,再将新的数值通过下标插入进去。
- void SLInsert(SL* ps, int pos, SLDataType x)
- {
- assert(ps);
-
- assert(pos >= 0 && pos <= ps->size);
- SLCheckCapacity(ps);
-
- int end = ps->size - 1;
- while (end >= pos)
- {
- ps->a[end + 1] = ps->a[end];
- --end;
- }
- ps->a[pos] = x;
- ps->size++;
- }

主体思想:通过下标来找到那个位置的值,让后面的数值向前面进行覆盖。
- void SLErase(SL* ps, int pos)
- {
- assert(ps);
-
- assert(pos >= 0 && pos < ps->size);
-
- int begin = pos + 1;
- while (begin < ps->size)
- {
- ps->a[begin - 1] = ps->a[begin];
- ++begin;
- }
-
- ps->size--;
- }

主体思想:将指针指向的空间释放,然后在将该空间赋为空。
- void SLDestroy(SL* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->capacity = ps->size = 0;
- }
主体思想:和打印数组相同
- void SLPrint(SL* ps)
- {
- assert(ps);
- for (int i = 0; i < ps->size; i++)
- {
- printf("%d ", ps->a[i]);
- }
- printf("\n");
- }
主体思想:通过下标找到该元素,对该元素进行再次赋值
- void SLModify(SL* ps, int pos, SLDataType x)
- {
- assert(ps);
-
- assert(pos >= 0 && pos < ps->size);
-
- ps->a[pos] = x;
- }

以上就是数据结构当中的顺序表的全部功能的实现,通过思想和代码实现,和效果图让初学者也可以快速上手。