动态顺序表
- 以下增删查操作是索引为index的下标,具体根据要求做改动
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
typedef int ElemType;
typedef struct {
ElemType *data;
int length; //当前的长度
int maxSize;//最大长度
} SqlList;
//初始化
void initList(SqlList &L) {
L.data = (ElemType *) malloc(initSize * sizeof(ElemType));
L.length = 0;
L.maxSize = initSize;
}
//开辟空间
void createLength(SqlList &L, int size) {
ElemType *p = L.data; //备份转移数据
L.data = (ElemType *) malloc((size + L.maxSize) * sizeof(ElemType));
// 转移数据
for (int i = 0; i < L.length; i++) {
L.data[i] = p[i];
}
L.maxSize += size;
free(p);
}
//插入
int insertElem(SqlList &L, int index, ElemType x) {
//判断合法性
if (index < 0 || index > L.length)return 0;
for (int i = L.length; i > index; --i) {
L.data[i] = L.data[i - 1];
}
L.data[index] = x;
L.length += 1;
return 1;
}
//删除
int deleteElem(SqlList &L, int index, ElemType &e){
//判断合法性
if (index < 0 || index > L.length)return 0;
e = L.data[index];
for (int i = index; i < L.length - 1; ++i) {
L.data[i] = L.data[i+1];
}
L.length -= 1;
return 1;
}
//获取元素
ElemType getElem(SqlList L, int index){
//判断合法性
if (index < 0 || index > L.length)return 0;
return L.data[index];
}
//查找元素,有就返回下标,没有就返回-1
int findElem(SqlList L, ElemType x){
for (int i = 0; i < L.length; ++i) {
if (L.data[i] == x) return i;
}
return -1;
}
//打印
void showList(SqlList L){
for (int i = 0; i < L.length; ++i) {
printf("%d ", L.data[i]);
}
printf("length = %d \n", L.length);
}
int main() {
SqlList l;
ElemType x;
initList(l);
for(int i = 0;i<10;i++){
insertElem(l, i, i);
}
showList(l);
insertElem(l, 5, 999);
showList(l);
deleteElem(l,2, x);
showList(l);
printf("%d \n", getElem(l, 7));
printf("find: %d\n", findElem(l,9));
return 0;
}单链表
定义
- 带头节点的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef int ElemType;
typedef struct Node {
struct Node *next;
ElemType data;
} LNode, *LinkList; //LinkList 和 LNode*是一样的
//带头结点的会更方便,这里是带头节点的
bool initList(LinkList &l) {
l = (LNode *) malloc(sizeof(LNode));//LNode*强调的是分配一个节点,也可以l = (LinkList)malloc(sizeof(LNode));
//判断内存够不够,其实可以不用
if (l == NULL) return false;
l->next = NULL;
return true;
} - 插入和删除本质上都是找到前面一个节点
插入操作
- 带头节点的插入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//在第i个位置插入节点,本质上要找到第i-1个节点,以头节点为第0个节点
bool insertElem(LinkList &l, int i, ElemType x) {
if (i < 1)return false;
LinkList p = l; //p开始指向头节点l,Lnode* p = l;
int j = 0; //j表示当前p指向节点的下标
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
if (p == NULL) return false;//i不合法,i太大,远超过节点个数
//到这里时,p已经到了i-1这个位置,可以开辟一块空间了
LNode *s = (LNode *) malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
return true;
} - 如果是不带头节点的
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//不带头节点的插入
bool insertElemNoH(LinkList &l, int i, ElemType x) {
if (i < 0)return false;
//单独处理插入第一个节点的情况
if (i == 1) {
LNode *s = (LNode *) malloc(sizeof(LNode));
s->data = x;
s->next = l;
l = s;
return true;
}
//下面操作和带头节点的操作是一样的
LNode *p = l;
int j = 1;
while (p && j < i - 1) {
p = p->next;
j++;
}
if (!p)return false;
LNode *s = (LNode *) malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
return true;
}前插操作
1
2
3
4
5
6
7
8
9
10
11//前插操作,在节点p前面插入一个节点,值为x
//时间复杂度为O(1)
bool insertPriorNode(LinkList &l, LNode *p, ElemType x) {
if (!p)return false;
LNode *s = (LNode *) malloc(sizeof(LNode));
s->next = p->next;
s->data = p->data;
p->next = s;
p->data = x;
return true;
} - 和上面本质一样,其实是交换数据
1
2
3
4
5
6
7
8
9
10//对于指定节点的前插操作,比如在p节点前插入s节点
bool insertPNode(LNode *p, LNode *s) {
if (!p || !s)return false;
s->next = p->next;
p->next = s;
ElemType temp = s->data;
s->data = p->data;
p->data = temp;
return true;
}删除操作
1 | //删除第i个节点,由x带回值 |
- 删除要注意一个细节
1
2if (!p)return false;//i不合法
if (!(p->next))return false;//i-1后面没有节点了删除指定节点
1
2
3
4
5
6
7
8
9//删除指定的节点
bool deleteTElem(LNode* p){
if(!p || !(p->next)) return false;
LNode *s = p->next;
p->data = s->data;
p->next = s->next;
free(s);
return true;
} - 参考
查找
按位查找
1 | //按位查找,找到第i个 |
按值查找
1 | //按值查找 |
求表长
- 这是带头节点的,注意表头不算如长度
1 | //求表的长度 |
单链表的建立
- 头插法
- 尾插法
尾插法
1 | //尾插法 |
头插法
1 | //头插法 |
双链表
定义
1 | typedef int ElemType; |
初始化
1 | //初始化 |
后插
1 | //在p节点后面插入s节点 |
前删
1 | //在节点p后面删除节点q |
销毁
1 | //销毁,即每一次都删除头节点的下一个节点 |
双向循环链表
- 更加方便
- 实现比上面简单
顺序栈
1 | // 顺序栈 |
链式栈
1 | // 链式栈 |
1 | 9 8 7 6 5 4 3 2 1 0 |
顺序循环队列
- 在判断队空和队满时有3种方法,看教材
- 这里列举其中一种
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
typedef int ElemType;
typedef struct {
int rear, front; //front指向队头第一个,rear指向队尾的下一个
ElemType data[maxSize];
} SeqQueue;
//初始化
void initQueue(SeqQueue &q) {
q.front = q.rear = 0;
}
//判断空
bool isEmpty(SeqQueue q) {
return q.rear == q.front;
}
//入队
bool enQueue(SeqQueue &q, ElemType x) {
if ((q.rear + 1) % maxSize == q.front) return false; //已满的情况
q.data[q.rear] = x;
q.rear %= maxSize;
return true;
}
//出队
bool deQueue(SeqQueue &q, ElemType &x) {
if (q.rear == q.front) return false;
x = q.data[q.front];
q.front = (q.front + 1) % maxSize;
return true;
}
//获取队头元素
ElemType getTop(SeqQueue q) {
if (q.rear == q.front) return false;
return q.data[q.front];
}
//计算对内元素的个数
int getNum(SeqQueue q){
return (q.rear + maxSize -q.front) % maxSize;
}链式队列
1 |
|
排序算法
算法的稳定性
比如,排序的数组中有两个数是一样的,那么排序后他们的相对位置如果没有变,那就说明这个排序算法是稳定的,否则是不稳定的
插入排序
- 开始时:

- 比较过程,排序

- i前面的元素已经是排序好的了,i所指的元素依次和i前面一个元素比较,如果有比a[i]大的,就要排序了。就先把a[i]保存到temp,然后,temp依次前面的元素比较,如果
a[j] > temp
,也就是前面的元素仍然大于temp,那么就前面的元素持续依次后移,直到前面所有元素全部比较完为止。
1 |
|
1 | 0 1 2 3 6 7 9 9 23 54 |
- 空间复杂度:O(1)
- 平均时间复杂度:O(n^2),最好是O(n),最坏是O(n^2)
- 算法的稳定性:稳定
冒泡排序
以下按递增顺序来看
- 迭代n趟,每趟依次比较相邻的两个元素,如果
a[j]>a[j+1]
,就交换彼此 - 经过一趟下来,最右边的元素是最大的
- 优化:
- 在第二个for的判断中,如果两两元素都没发生交换,那就说明排序已经全部排好了,可以结束排序了,设置标志跳出即可
1 | void bubbleSort(int a[], int n) { |
空间复杂度:O(1)
时间复杂度:最好O(n),最坏O(n^2),平均是O(n^2)
稳定性:稳定
每次交换,都需要移动元素次数三次
1
2
3temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;移动次数和交换次数不同
交换次数最少是0,最多是n(n-1)/2
选择排序
- 找到最小的和每一趟前面的第一个元素交换
- 外层n-1趟
1 | void chooseSort(int a[], int n) { |
- 稳定性:不稳定
- 空间复杂度:O(1)
- 时间复杂度:O(n^2)