赞
踩
数据结构常见的结构有线性结构、树型结构、图形结构。
而线性结构又分为线性表、栈、数组、队列,本文讲的是顺序表,是线性表的一种。
- #pragma once
- #include<stdio.h>
- #include<assert.h>
- #include<stdlib.h>
- #define Max_Capacity 10
-
-
- typedef int SLDateType;
- //顺序表
- typedef struct SeqList
- {
- //顺序表地址q
- SLDateType* a;
- //顺序表的有效长度
- int size;
- //顺序表大小
- int capacity;
- }SeqList;
-
- //初始化顺序表
- void SeqListInit(SeqList* ps);
- //销毁顺序表
- void SeqListDestroy(SeqList* ps);
-
-
- //打印顺序表
- void SeqListPrint(SeqList* ps);
- //头插
- void SeqListPushFront(SeqList* ps, SLDateType x);
- //尾插
- void SeqListPushBack(SeqList* ps, SLDateType x);
- //头删
- void SeqListPopFront(SeqList* ps);
- //尾删
- void SeqListPopBack(SeqList* ps);
- //中间插
- void SeqListInsert(SeqList* ps, int pos, int x);
- //中间删
- void SeqListErase(SeqList* ps, int pos);
-
-
- //检查顺序表是否满了
- SLDateType SeqListFull(SeqList* ps);
- //顺序表扩容
- void SeqListAdd(SeqList* ps);
-
-
- //顺序表中查数
- void SeqListSearch(SeqList* ps, SLDateType x);
- //顺序表中改数
- void SeqListChange(SeqList* ps, SLDateType x,SLDateType y);

- #include"SeqList.h"
-
- //初始化顺序表
- void SeqListInit(SeqList* ps)
- {
- ps->a = NULL;
- ps->size = 0;
- ps->capacity = 0;
- }
-
- //打印顺序表
- void SeqListPrint(SeqList* ps)
- {
- assert(ps);
- if (ps->size == 0)
- {
- printf("顺序表无有效数据\n");
- return;
- }
- for (SLDateType i = 0; i < ps->size; i++)
- {
- printf("%d ", *(ps->a + i));
- }
- printf("\n");
- }
-
- //销毁顺序表
- void SeqListDestroy(SeqList* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->size = 0;
- ps->capacity = 0;
- }
-
- //判断顺序表是否满了
- SLDateType SeqListFull(SeqList* ps)
- {
- assert(ps);
- if (ps->size == ps->capacity)
- {
- return 1;
- }
- return 0;
- }
-
- //扩容
- void SeqListAdd(SeqList* ps)
- {
- assert(ps);
- ps->a = (SLDateType*)realloc(ps->a,ps->capacity*2*sizeof(SLDateType));
- if (ps->a == NULL)
- {
- perror("realloc error");
- exit(-1);
- }
- ps->capacity *= 2;
- }
-
- //头插
- void SeqListPushFront(SeqList* ps, SLDateType x)
- {
- assert(ps);
- if (ps->size < 0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- for(SLDateType i = ps->size-1; i >=0; i--)
- {
- ps->a[i + 1] = ps->a[i];
- }
- ps->a[0] = x;
- ps->size++;
- }
-
- //尾插
- void SeqListPushBack(SeqList* ps, SLDateType x)
- {
- assert(ps);
- if (ps->size < 0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- ps->a[ps->size] = x;
- ps->size++;
- }
-
- //头删
- void SeqListPopFront(SeqList* ps)
- {
- assert(ps);
- if (ps->size <=0)
- {
- ps->size = 0;
- return;
- }
- for (SLDateType i = 1; i < ps->size; i++)
- {
- ps->a[i - 1] = ps->a[i];
- }
- ps->size--;
- }
-
- //尾删
- void SeqListPopBack(SeqList* ps)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- ps->size--;
- }
-
- //中间插
- void SeqListInsert(SeqList* ps,int pos,int x)
- {
- assert(ps);
- if (ps->size <0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- if (pos - 1 < ps->size)
- {
- for(SLDateType i = ps->size - 1; i >= pos - 1; i--)
- ps->a[i + 1] = ps->a[i];
- ps->a[pos - 1] = x;
- ps->size++;
- }
- else
- printf("插入无效\n");
- }
-
- //中间删
- void SeqListErase(SeqList* ps, int pos)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- if (pos - 1 < ps->size)
- {
- for (SLDateType i = pos; i < ps->size; i++)
- ps->a[i - 1] = ps->a[i];
- ps->size--;
- }
- else
- printf("删除无效\n");
- }
-
- //查
- void SeqListSearch(SeqList* ps, int pos)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- }
- if (pos - 1 < ps->size)
- {
- printf("%d\n",ps->a[pos - 1]);
- return;
- }
- printf("查找无效\n");
- }
-
- //改
- void SeqListChange(SeqList* ps, int pos, int x)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- if (pos - 1 < ps->size)
- {
- ps->a[pos - 1] = x;
- }
- else
- printf("修改无效\n");
- }

- #define _CRT_SECURE_NO_WARNINGS 1
- #include"SeqList.h"
- SLDateType main()
- {
- //创造顺序表
- SeqList sl;
- //初始化
- SeqListInit(&sl);
- sl.capacity = Max_Capacity;
- sl.a = (SLDateType*)realloc(sl.a,sl.capacity * sizeof(SLDateType));
- if (sl.a == NULL)
- {
- perror("realloc error");
- exit(-1);
- }
- //尾插012345
- for (SLDateType i = 0; i < 5; i++)
- SeqListPushBack(&sl, i);
- //打印顺序表
- SeqListPrint(&sl);
- //头插012345
- for (SLDateType i = 0; i < 5; i++)
- SeqListPushFront(&sl, i);
- //再次打印
- SeqListPrint(&sl);
- //尾删3个数
- for (SLDateType i = 0; i < 3; i++)
- SeqListPopBack(&sl);
- SeqListPrint(&sl);
- //头删2个数
- for(SLDateType i=0;i<2;i++)
- SeqListPopFront(&sl);
- SeqListPrint(&sl);
- //中间第三个数插入2
- SeqListInsert(&sl, 3, 2);
- SeqListPrint(&sl);
- //中间第三个数删除
- SeqListErase(&sl, 3);
- SeqListPrint(&sl);
- //查找第3个数
- SeqListSearch(&sl, 3);
- //修改第3个数为100
- SeqListChange(&sl, 3, 100);
- SeqListPrint(&sl);
- //销毁顺序表
- SeqListDestroy(&sl);
- return 0;
- }

- typedef int SLDateType;
- //顺序表
- typedef struct SeqList
- {
- //顺序表地址q
- SLDateType* a;
- //顺序表的有效长度
- int size;
- //顺序表大小
- int capacity;
- }SeqList;
创建一个顺序表结构体,成员包含顺序表地址、长度、大小,用于创建顺序表变量。
- //初始化顺序表
- void SeqListInit(SeqList* ps)
- {
- ps->a = NULL;
- ps->size = 0;
- ps->capacity = 0;
- }
将顺序表变量的地址传参,通过指针接收对顺序表的顺序表数组初始化为空,长度为0,大小为0。
- //打印顺序表
- void SeqListPrint(SeqList* ps)
- {
- assert(ps);
- if (ps->size == 0)
- {
- printf("顺序表无有效数据\n");
- return;
- }
- for (SLDateType i = 0; i < ps->size; i++)
- {
- printf("%d ", *(ps->a + i));
- }
- printf("\n");
- }
同样传地址,要先断言指针是否为空,不然会出异常。
然后判断顺序表大小是否为0,为0则代表顺序表中没有有效元素,打印提示,并返回函数,如果大于0,则有元素,从下标0开始,打印size个顺序表元素,并用空格相隔。
- //销毁顺序表
- void SeqListDestroy(SeqList* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->size = 0;
- ps->capacity = 0;
- }
当我们结束程序时,因为我们是通过动态分配空间给顺序表,所以结束时我们要手动销毁,先断言,防止free空指针,成功释放空间后,将ps->a手动置空,避免产生野指针,并将大小、空间赋0。
- //头插
- void SeqListPushFront(SeqList* ps, SLDateType x)
- {
- assert(ps);
- if (ps->size < 0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- for(SLDateType i = ps->size-1; i >=0; i--)
- {
- ps->a[i + 1] = ps->a[i];
- }
- ps->a[0] = x;
- ps->size++;
- }

在头部插入数据,要先判断容量是否已满,如果已满,需要扩容,还有空间,那么就从下标为ps->size-1开始,到0上的值都要将前一个元素给覆盖,而将要插入的数据覆盖给下标为0的空间,长度加1。
- //尾插
- void SeqListPushBack(SeqList* ps, SLDateType x)
- {
- assert(ps);
- if (ps->size < 0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- ps->a[ps->size] = x;
- ps->size++;
- }
都是插入数据,所以前面的操作和头插一致,但是尾插要比头插看起来方便,因为只要在顺序表后一个空间内插入要插入的数据,不需要移动数据,并将长度+1。
-
- //头删
- void SeqListPopFront(SeqList* ps)
- {
- assert(ps);
- if (ps->size <=0)
- {
- ps->size = 0;
- return;
- }
- for (SLDateType i = 1; i < ps->size; i++)
- {
- ps->a[i - 1] = ps->a[i];
- }
- ps->size--;
- }

判断部分不需要判断容量是否够,且长度不能为负数。
和头插相反,我们要从下标为1,到ps->size-1,将前一个数覆盖,长度减1。
- //尾删
- void SeqListPopBack(SeqList* ps)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- ps->size--;
- }
判断部分一致,尾删只需将长度减一即可。
- //中间插
- void SeqListInsert(SeqList* ps,int pos,int x)
- {
- assert(ps);
- if (ps->size <0)
- {
- ps->size = 0;
- }
- if (SeqListFull(ps))
- {
- SeqListAdd(ps);
- }
- if (pos - 1 < ps->size)
- {
- for(SLDateType i = ps->size - 1; i >= pos - 1; i--)
- ps->a[i + 1] = ps->a[i];
- ps->a[pos - 1] = x;
- ps->size++;
- }
- else
- printf("插入无效\n");
- }

中间插比较麻烦,不仅要断言,判断ps->size是否合理,容量是否够,还要判断所给插入数据下标位置是否在0到ps->size之间的合法区域,所以以上同时合法时, 才能实现插入数据,和头插相似,它们都是先从尾部数据开始,先向右整体覆盖过去,但是头插是到0停止,而中间插是到所给下标停止,并将该下标的数插入为想插入的数据,长度加1。
- //中间删
- void SeqListErase(SeqList* ps, int pos)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- if (pos - 1 < ps->size)
- {
- for (SLDateType i = pos; i < ps->size; i++)
- ps->a[i - 1] = ps->a[i];
- ps->size--;
- }
- else
- printf("删除无效\n");
- }

和头删相似,将指定下标左边的元素往左移动一个空间,长度减1。
- //查
- void SeqListSearch(SeqList* ps, int pos)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- }
- if (pos - 1 < ps->size)
- {
- printf("%d\n",ps->a[pos - 1]);
- return;
- }
- printf("查找无效\n");
- }
返回指定下标下的值,比较容易实现。
- //改
- void SeqListChange(SeqList* ps, int pos, int x)
- {
- assert(ps);
- if (ps->size <= 0)
- {
- ps->size = 0;
- return;
- }
- if (pos - 1 < ps->size)
- {
- ps->a[pos - 1] = x;
- }
- else
- printf("修改无效\n");
- }

找到指定下标的位置,直接赋给修改的值即可,也很容易实现。
- /判断顺序表是否满了
- SLDateType SeqListFull(SeqList* ps)
- {
- assert(ps);
- if (ps->size == ps->capacity)
- {
- return 1;
- }
- return 0;
- }
-
- //扩容
- void SeqListAdd(SeqList* ps)
- {
- assert(ps);
- ps->a = (SLDateType*)realloc(ps->a,ps->capacity*2*sizeof(SLDateType));
- if (ps->a == NULL)
- {
- perror("realloc error");
- exit(-1);
- }
- ps->capacity *= 2;
- }

如果ps->size等于容量,代表容量已满,则将容量扩大为原来的两倍,但是可能会出现内存泄漏的情况,严谨一点应该在realloc完后将地址赋给一个新指针,由新指针判断不为空,再赋给顺序表指针,如果扩容失败,程序将会终止。
- #define _CRT_SECURE_NO_WARNINGS 1
- #include"SeqList.h"
- SLDateType main()
- {
- //创造顺序表
- SeqList sl;
- //初始化
- SeqListInit(&sl);
- sl.capacity = Max_Capacity;
- sl.a = (SLDateType*)realloc(sl.a,sl.capacity * sizeof(SLDateType));
- if (sl.a == NULL)
- {
- perror("realloc error");
- exit(-1);
- }
- //尾插01234
- for (SLDateType i = 0; i < 5; i++)
- SeqListPushBack(&sl, i);
- //打印顺序表
- SeqListPrint(&sl);
- //头插01234
- for (SLDateType i = 0; i < 5; i++)
- SeqListPushFront(&sl, i);
- //再次打印
- SeqListPrint(&sl);
- //尾删3个数
- for (SLDateType i = 0; i < 3; i++)
- SeqListPopBack(&sl);
- SeqListPrint(&sl);
- //头删2个数
- for(SLDateType i=0;i<2;i++)
- SeqListPopFront(&sl);
- SeqListPrint(&sl);
- //中间第三个数插入2
- SeqListInsert(&sl, 3, 2);
- SeqListPrint(&sl);
- //中间第三个数删除
- SeqListErase(&sl, 3);
- SeqListPrint(&sl);
- //查找第3个数
- SeqListSearch(&sl, 3);
- //修改第3个数为100
- SeqListChange(&sl, 3, 100);
- SeqListPrint(&sl);
- //销毁顺序表
- SeqListDestroy(&sl);
- return 0;
- }

用SeqList.c的函数实现我们对顺序表sl的一系列操作,结束时销毁顺序表。
打印结果如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。