image-20210602112335408

结构体定义

1
2
3
4
5
6
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;

打印

1
2
3
4
5
6
7
8
9
10
void SLTPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur !=NULL)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}

创建结点

1
2
3
4
5
6
7
SLTNode* SLTCreat(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}

尾插

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
//创建新结点
SLTNode* newnode = SLTCreat(x);
//如果是空链表
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
//找到尾结点
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}

头插

1
2
3
4
5
6
7
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
//创建新结点
SLTNode* newnode = SLTCreat(x);
newnode->next = *pphead;
*pphead = newnode;
}

尾删

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
void SLTPopBack(SLTNode** pphead)
{
//空链表
if (*pphead == NULL)
{
return ;
}
//链表中只有一个结点
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//一个以上结点
else
{
//找到尾结点
SLTNode* tail = *pphead;
//找到尾结点的前一个结点
SLTNode* tailPrev = NULL;
while (tail->next != NULL)
{
tailPrev = tail;
tail = tail->next;
}
free(tail);
tailPrev->next = NULL;

}

}

头删

1
2
3
4
5
6
7
8
9
void SLTPopFront(SLTNode** pphead)
{
//如果直接free pphead就会找不到后面的结点了
//先保存下一个
SLTNode* ppheadNext = (*pphead)->next;//这里要加一个括号,因为*和->都是解引用,*是对任意的指针都可以解引用,取它指向的这个位置的数据,什么类型的指针就取几个字节,->是结构体的,这时候他们两个的优先级是一样的。
free(*pphead);
//这时候第一个数据就是之前第二个数据了
*pphead = ppheadNext;
}

查找

下面的删除和插入都要在先在链表中找到为前提。

1
2
3
4
5
6
7
8
9
10
11
12
13
SLTNode* SLTFind(SLTNode* phead,SLTDataType x)
{
SLTNode* pos = phead;
while (pos != NULL)
{
if (pos->data == x)
{
return pos;
}
pos = pos->next;
}
return NULL;
}

在指定位置前插入某个数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDataType x)
{
//如果在第一个结点前插入数据
//那就是头插,直接调用头插的函数
if (pos == *pphead)
{
SLTPushFront(pphead,x);
}
else
{
//创建一个新结点来存放新的数据
SLTNode* newnode = SLTCreat(x);
//要在pos前面插入newnode,就得先找到pos前面的内个结点
SLTNode* posPrev = *pphead;
while (posPrev->next != pos)
{
posPrev = posPrev->next;
}
//链接起来
posPrev->next = newnode;
newnode->next = pos;
}
}

删除指定位置数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void SLTErase(SLTNode** pphead, SLTNode*pos)
{
//当删除第一个结点的时候,无法找到他的前一个结点
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else
{
//单链表每次老是要寻找前一个结点
SLTNode* posPrev = *pphead;
while (posPrev->next != pos)
{
posPrev = posPrev->next;
}
posPrev->next = pos->next;
free(pos);
}
}

全部代码

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include<stdio.h>
#include<stdlib.h>
//定义结构
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
//改变头结点的传2级指针,不改变的传1级指针
//打印
void SLTPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur !=NULL)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
//创建结点
SLTNode* SLTCreat(SLTDataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
//创建新结点
SLTNode* newnode = SLTCreat(x);
//如果是空链表
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
//找到尾结点
SLTNode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
//创建新结点
SLTNode* newnode = SLTCreat(x);
newnode->next = *pphead;
*pphead = newnode;
}
//尾删
void SLTPopBack(SLTNode** pphead)
{
//空链表
if (*pphead == NULL)
{
return ;
}
//链表中只有一个结点
else if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//一个以上结点
else
{
//找到尾结点
SLTNode* tail = *pphead;
//找到尾结点的前一个结点
SLTNode* tailPrev = NULL;
while (tail->next != NULL)
{
tailPrev = tail;
tail = tail->next;
}
free(tail);
tailPrev->next = NULL;

}

}
//头删
void SLTPopFront(SLTNode** pphead)
{
//如果直接free pphead就会找不到后面的结点了
//先保存下一个
SLTNode* ppheadNext = (*pphead)->next;//这里要加一个括号,因为*和->都是解引用,*是对任意的指针都可以解引用,取它指向的这个位置的数据,什么类型的指针就取几个字节,->是结构体的,这时候他们两个的优先级是一样的。
free(*pphead);
//这时候第一个数据就是之前第二个数据了
*pphead = ppheadNext;
}
//查找
SLTNode* SLTFind(SLTNode* phead,SLTDataType x)
{
SLTNode* pos = phead;
while (pos != NULL)
{
if (pos->data == x)
{
return pos;
}
pos = pos->next;
}
return NULL;
}
//在pos前插入某个数据
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDataType x)
{
//如果在第一个结点前插入数据
//那就是头插,直接调用头插的函数
if (pos == *pphead)
{
SLTPushFront(pphead,x);
}
else
{
//创建一个新结点来存放新的数据
SLTNode* newnode = SLTCreat(x);
//要在pos前面插入newnode,就得先找到pos前面的内个结点
SLTNode* posPrev = *pphead;
while (posPrev->next != pos)
{
posPrev = posPrev->next;
}
//链接起来
posPrev->next = newnode;
newnode->next = pos;
}
}
//删除pos位置的数据
void SLTErase(SLTNode** pphead, SLTNode*pos)
{
//当删除第一个结点的时候,无法找到他的前一个结点
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else
{
//单链表每次老是要寻找前一个结点
SLTNode* posPrev = *pphead;
while (posPrev->next != pos)
{
posPrev = posPrev->next;
}
posPrev->next = pos->next;
free(pos);
}
}
//测试
void Test1()
{
SLTNode* plist = NULL;
SLTPushBack(&plist, 0);
SLTPushBack(&plist, 2);
SLTPushBack(&plist, 3);
SLTPushBack(&plist, 4);
SLTPrint(plist);

SLTNode* pos = SLTFind(plist, 0);
if (pos != NULL)
{
//说明找到了
SLTErase(&plist, pos);
}
SLTPrint(plist);


}
int main(void)
{
Test1();
return 0;
}