img

✨✨所属专栏:数据结构✨✨

✨✨作者主页:嶔某✨✨

概念:

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。顺序表的本质就是数组,动态增长,并且要求里面存储的数据必须是从左往右连续的。逻辑结构与物理结构是一致的。

它分为静态顺序表(容量不可修改)和动态顺序表(可修改容量,可任意增删查改数据)

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不为空
//memset(ps->data, 0, sizeof(SQDataType) * 4);
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/imghttps://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->data[ps->size - 1] = 0;//有没有都无所谓,有效数据是用size来表示的
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不为空
//memset(ps->data, 0, sizeof(SQDataType) * 4);
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->data[ps->size - 1] = 0;//有没有都无所谓,有效数据是用size来表示的
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;
}

本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!