顺序表
说起数据结构(清华大学出版社)这本书,学到的第一个数据结构就是顺序表,顾名思义顺序表啥意思呢,就是字面意思。指用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表在逻辑结构上相邻的元素存储在连续的物理存储单元中,即:通过数据元素物理存储的连续性来反应元素之间逻辑上的相邻关系。采用顺序存储结构存储的线性表通常简称为顺序表。 我们最常用的数组,其实就是一种顺序表中的典型。
-
顺序表存储示意
-
c语言定义顺序表储存结构
typedef struct SeqList { DataType array[MAX_SIZE]; int size; //1.保存顺序表里已经存了的数据个数; //2.当前用下标。 } SeqList;
- DataType 的作用,我们知道在实际使用数据结构时,我们不免需要用到各种类型的数据,那么DataType的作用,就是预先不给定具体类型,由使用者决定是什么类型,这种思想叫做泛型编程。
- MAX_SIZE的作用,不给定具体数字大小,而使用常量,为了代码的灵活,如果多次需要这个量,那么我们设置其为常量不是更好吗?
-
预定义
// 抽象类型 数据本身不仅仅是数组,更以各种形式所表现。 typedef int DataType; #define MAX_SIZE 100
-
顺序表需要设置那些接口?
用户基本业务需求就是CRUD(增删改查),那么顺序表自身呢,就需要初始化和销毁的完整生命周期。-
初始化和销毁
- 初始化
assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。void SeqListInit(SeqList* pSeq) { // 1.初始化size // 2.可能需要把容器清空 // 1. assert(pSeq != NULL) // 2.if(pSeq != NULL) assert(pSeq != NULL); pSeq->size = 0; // memset(pSeq->array, 0, MAX_SIZE) }
- 销毁
// 销毁 void SeqListDestroy(SeqList* pSeq) { assert(pSeq); pSeq->size = 0; }
- 初始化
-
增加数据
分为三种情况
- 加在头
- 加在尾
- 加在中间
注意:前提条件是顺序表不能满
- 头插
void SeqListPushFront(SeqList* pSeq, DataType data) { assert(pSeq); if (pSeq->size == MAX_SIZE) { return; } //从最后元素,向更后搬运 // i代表位置 for (int i = pSeq->size; i > 0; i--) { pSeq->array[i] = pSeq->array[i - 1]; } // i代表数据 /*for (int i = pSeq->size - 1; i >= 0; i--) { pSeq->array[i + 1] = pSeq->array[i]; }*/ pSeq->array[0] = data; pSeq->size++; }
- 尾插
void SeqListPushBack(SeqList* pSeq, DataType data) { assert(pSeq); //特殊情况 1. 满了 if (pSeq->size == MAX_SIZE) { assert(0); return; } //通常情况 pSeq->array[pSeq->size] = data; pSeq->size++; }
- 选择插入(中间插)
void SeqListPushIndex(SeqList* pSeq,int index, DataType data) { assert(pSeq); assert(index >= 0 && index <= pSeq->size); if (pSeq->size == MAX_SIZE) { return; } for (int i = pSeq->size; i > index; i--) { pSeq->array[i] = pSeq->array[i - 1]; } pSeq->array[index] = data; pSeq->size++; }
-
删除数据
与插入一样分为三种情况
-
尾删
void SeqListPop(SeqList* pSeq) { assert(pSeq); // 特殊情况 空了 if (pSeq->size == 0) { return; } // 通常情况 pSeq->size--; }
-
头删
void SeqListPopFront(SeqList* pSeq) { assert(pSeq); if (pSeq->size == 0) { printf("空的\n"); return; } for (int i = 0; i < pSeq->size-1; i++) { pSeq->array[i] = pSeq->array[i + 1]; } pSeq->size--; }
-
选择删除
void SeqListErase(SeqList* pSeq, int index) { assert(pSeq); assert(index >= 0 && index <= pSeq->size - 1); if (pSeq->size == 0) { printf("空的"); return; } for (int i = index; i < pSeq->size-1; i++) { pSeq->array[i] = pSeq->array[i + 1]; } pSeq->size--; }
-
- 查找数据
//找到第一个遇到的数的下标, 没找到返回 -1 int SeqListFind(SeqList* pSeq, DataType data) { //二分查找 有序 for (int i = 0; i < pSeq->size; i++) { if (data == pSeq->array[i]) { return i; } } return -1; } //根据输入的元素,删除遇到的第一个数据. void SeqListRemove(SeqList* pSeq, DataType data) { int index = SeqListFind(pSeq, data); if (index == -1) { return; } SeqListErase(pSeq, index); } //删除遇到的所有数据 void SeqListRemoveAll(SeqList* pSeq, DataType data) { DataType* extra = (DataType*)malloc(sizeof(DataType) * pSeq->size); int i = 0, j = 0; for (; i < pSeq->size; i++) { if (pSeq->array[i] != data) { extra[j++] = pSeq->array[i]; } } for (int k = 0; k < j; k++) { pSeq->array[k] = extra[k]; } pSeq->size = j; free(extra); }
-
写在最后
最近推出了公众号 coding趣谈,一位在读学生的技术提升之路,为您提供一系列我在学习路上的笔记,经验,以及感悟。往与君共勉,共同进步! 欢迎大家来关注哦!