
✨✨所属专栏:数据结构✨✨
✨✨作者主页:嶔某✨✨
概念:
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。顺序表的本质就是数组,动态增长,并且要求里面存储的数据必须是从左往右连续的。逻辑结构与物理结构是一致的。
它分为静态顺序表(容量不可修改)和动态顺序表(可修改容量,可任意增删查改数据)
SeqList.h
定义顺序表,声明函数。这里size表示有效数据,capacity表示可用空间大小,data是存储数据的指针(可以看作一个数组)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #pragma once #include<assert.h> #include<stdio.h> #include<stdlib.h>
typedef int SQDataType;
typedef struct SeqList { SQDataType* data; int size; int capacity; }SLT;
void SeqListPrint(SLT* ps); void SeqListInit(SLT* ps); void SeqListDistory(SLT* ps); void SeqListCheckCapacity(SLT* ps); void SeqListPushBack(SLT* ps, SQDataType x); void SeqListPushFront(SLT* ps, SQDataType x); void SeqListPopBack(SLT* ps); void SeqListPopFront(SLT* ps); void SeqListInsert(SLT* ps, int pos, SQDataType x); void SeqListErase(SLT* ps, int pos); int SeqListFind(SLT* ps, SQDataType x); void SeqListModity(SLT* ps,int pos,SQDataType x);
|
这里我们介绍十二种接口。
初始化:
1 2 3 4 5 6 7
| void SeqListInit(SLT* ps) { assert(ps); ps->data = NULL; ps->size = ps->capacity = 0; }
|
把data置为空,size,capacity置为0,进行初始化。
打印:
1 2 3 4 5 6
| void SeqListPrint(SLT* ps) { for (int i = 0; i < ps->size; i++) printf("%d ", ps->data[i]); printf("\n"); }
|
打印就不过多讲了,记得换行。
销毁:
1 2 3 4 5 6
| void SeqListDistory(SLT* ps) { free(ps->data); ps->data = NULL; ps->capacity = ps->size = 0; }
|
销毁就是把内存还给系统。直接free。
尾插:
1 2 3 4 5 6 7
| void SeqListPushBack(SLT* ps, SQDataType x) { SeqListCheckCapacity(ps);
ps->data[ps->size] = x; ps->size++; }
|
我们想插入一个数据,就先要判断空间是否足够。所以这里面就有了void SeqListCheckCapacity(SLT* ps);这个函数:
扩容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void SeqListCheckCapacity(SLT* ps) { if (ps->size == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SQDataType* tmp = realloc(ps->data, newcapacity * sizeof(SQDataType)); if (tmp == NULL) { printf("realloc is fail!\n"); exit(-1); } else { ps->data = tmp; ps->capacity = newcapacity; } } }
|
如果有效数据个数和有效空间相等那么就把空间扩至二倍。这里用到了realloc函数。详情见:cplusplus.com/reference/cstdlib/realloc/
https://cplusplus.com/reference/cstdlib/realloc/
头插:
1 2 3 4 5 6 7 8 9 10 11 12 13
| void SeqListPushFront(SLT* ps, SQDataType x) { SeqListCheckCapacity(ps);
int end = ps->size - 1; while (end >= 0) { ps->data[end + 1] = ps->data[end]; end--; } ps->data[0] = x; ps->size++; }
|
有了前面的基础,后面就容易多了。头插也要先判断空间是否足够,之后把数据从前往后挪,把ps->data[0]的地方空出来,将x放进去。
尾删:
1 2 3 4 5 6
| void SeqListPopBack(SLT* ps) { assert(ps->size > 0); ps->size--; }
|
这里的简单方法就是把size–就行,尾数置不置零都无所谓,因为算的都是在size范围内的有效数据。
头删:
1 2 3 4 5 6 7 8 9 10 11
| void SeqListPopFront(SLT* ps) { assert(ps->size > 0); int start = 0; while (start <= ps->size) { ps->data[start] = ps->data[start + 1]; start++; } ps->size--; }
|
这里直接从前往后挪,把第一个数据覆盖掉就行,然后size–。
指定插入:
1 2 3 4 5 6 7 8 9 10 11 12 13
| void SeqListInsert(SLT* ps,int pos, SQDataType x) { assert(pos <= ps->size); SeqListCheckCapacity(ps); int end = ps->size - 1; while (end >= pos) { ps->data[end + 1] = ps->data[end]; end--; } ps->data[pos - 1] = x; ps->size++; }
|
同样只要是插入数据,就要判断空间是否足够。然后把数据依次往后挪将ps->data[pos-1]这个位置空出来,把x放进去。
指定删除:
1 2 3 4 5 6 7 8 9 10 11
| void SeqListErase(SLT* ps, int pos) { assert(pos <= ps->size); int end = pos; while (end <= ps->size) { ps->data[end - 1] = ps->data[end]; end++; } ps->size--; }
|
采取同样的方法,将第pos位的数据覆盖,之后size–。
查找:
1 2 3 4 5 6 7 8 9
| int SeqListFind(SLT* ps, SQDataType x) { for (int i = 0; i < ps->size; i++) { if (ps->data[i] == x) return i; } return -1; }
|
这里暴力循环就好了,找到了就返回下标,否则返回-1,因为没有哪个数据的下标是-1的。
修改:
1 2 3 4 5
| void SeqListModity(SLT* ps, int pos, SQDataType x) { assert(pos < ps->size); ps->data[pos - 1] = x; }
|
这里直接将第pos位(ps->data[pos-1])修改成x就行。搞腚!
完整代码附上:
SeqList.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #define _CRT_SECURE_NO_WARNINGS 1 #include "Seqlist.h"
void SeqListInit(SLT* ps) { assert(ps); ps->data = NULL; ps->size = ps->capacity = 0; }
void SeqListDistory(SLT* ps) { free(ps->data); ps->data = NULL; ps->capacity = ps->size = 0; }
void SeqListPrint(SLT* ps) { for (int i = 0; i < ps->size; i++) printf("%d ", ps->data[i]); printf("\n"); }
void SeqListCheckCapacity(SLT* ps) { if (ps->size == ps->capacity) { int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; SQDataType* tmp = realloc(ps->data, newcapacity * sizeof(SQDataType)); if (tmp == NULL) { printf("realloc is fail!\n"); exit(-1); } else { ps->data = tmp; ps->capacity = newcapacity; } } }
void SeqListPushBack(SLT* ps, SQDataType x) { SeqListCheckCapacity(ps);
ps->data[ps->size] = x; ps->size++; }
void SeqListPushFront(SLT* ps, SQDataType x) { SeqListCheckCapacity(ps);
int end = ps->size - 1; while (end >= 0) { ps->data[end + 1] = ps->data[end]; end--; } ps->data[0] = x; ps->size++; }
void SeqListPopBack(SLT* ps) { assert(ps->size > 0); ps->size--; }
void SeqListPopFront(SLT* ps) { assert(ps->size > 0); int start = 0; while (start <= ps->size) { ps->data[start] = ps->data[start + 1]; start++; } ps->size--; }
void SeqListInsert(SLT* ps,int pos, SQDataType x) { assert(pos <= ps->size); SeqListCheckCapacity(ps); int end = ps->size - 1; while (end >= pos) { ps->data[end + 1] = ps->data[end]; end--; } ps->data[pos - 1] = x; ps->size++; }
void SeqListErase(SLT* ps, int pos) { assert(pos <= ps->size); int end = pos; while (end <= ps->size) { ps->data[end - 1] = ps->data[end]; end++; } ps->size--; }
int SeqListFind(SLT* ps, SQDataType x) { for (int i = 0; i < ps->size; i++) { if (ps->data[i] == x) return i; } return -1; }
void SeqListModity(SLT* ps, int pos, SQDataType x) { assert(pos < ps->size); ps->data[pos - 1] = x; }
|
本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!