C语言单链表实现方法详解

2025-05-27 0 89

本文实例讲述了C语言单链表实现方法。分享给大家供大家参考,具体如下:

slist.h

?

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
#ifndef __SLIST_H__

#define __SLIST_H__

#include<cstdio>

#include<malloc.h>

#include<assert.h>

typedef int ElemType;

typedef struct Node { //定义单链表中的结点信息

ElemType data; //结点的数据域

struct Node *next; //结点的指针域

}Node,*PNode;

typedef struct List { //定义单链表的链表信息

PNode first; //first指向单链表中的第一个结点

PNode last; //last指向单链表中的最后一个结点

size_t size; //记录单链表中的结点个数

}List;

void InitList(List *list);//初始化单链表

void push_back(List *list, ElemType x);//在单链表的末尾插入元素

void push_front(List *list, ElemType x);//在单链表的头部插入元素

void show_list(List *list);//打印单链表

void pop_back(List *list);//删除单链表的最后一个元素

void pop_front(List *list);//删除单链表的第一个元素

void insert_val(List *list, ElemType val);//将数据元素插入到单链表中(要求此时单链表中的数据元素顺序排列)

Node* find(List *list, ElemType x);//查找单链表中数据值为x的结点

int length(List *list);//求单链表的长度

void delete_val(List *list, ElemType x);//按值删除单链表中的某个数据元素

void sort(List *list);//对单链表进行排序

void reverse(List *list);//逆置单链表

void clear(List *list);//清除单链表

void destroy(List *list);//摧毁单链表

#endif //__SLIST_H__

slist.cpp

?

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
#include"slist.h"

void InitList(List *list) {

list->first = list->last = (Node*)malloc(sizeof(Node)); //头结点

assert(list->first != NULL);

list->first->next = NULL;

list->size = 0;

}

void push_back(List *list, ElemType x) {

//step 1:创建一个新的结点

Node *s = (Node*)malloc(sizeof(Node));

assert(s != NULL);

s->data = x;

s->next = NULL;

//step 2:将新结点插入单链表的表尾

list->last->next = s;

list->last = s;

//step 3:更新单链表的长度

list->size++;

}

void push_front(List *list, ElemType x) {

//step 1:创建一个新的结点

Node *s = (Node*)malloc(sizeof(Node));

assert(s != NULL);

s->data = x;

s->next = NULL;

//step 2:将新结点插入单链表的表头

s->next = list->first->next;

list->first->next = s;

//step 3:判断插入的结点是否是单链表的第一个结点,若是更新链表的尾指针

if (list->size == 0)

list->last = s;

//step 4:更新单链表的长度

list->size++;

}

void show_list(List *list) {

//step 1:指针p指向单链表的第一个结点

Node *p = list->first->next;

//step 2:循环打印结点的信息

while (p != NULL) {

printf("%d->", p->data);

p = p->next;

}

printf("Nul.\\n");

}

void pop_back(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:定义指针p使其指向目标结点的前一个结点

Node *p = list->first;//从头结点开始

while (p->next != list->last)

p = p->next;

//step 3:删除目标结点

free(list->last);

list->last = p;

list->last->next = NULL;

//step 4:更新单链表的长度

list->size--;

}

void pop_front(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:定义指针p使其指向目标结点的前一个结点

Node *p = list->first->next;

//step 3:删除目标结点

list->first->next = p->next;

free(p);

//step 4:判断删除的结点是否是单链表的最后一个结点,若是则更新单链表的尾指针

if (list->size == 1)

list->last = list->first;

//step 4:更新单链表的长度

list->size--;

}

void insert_val(List *list, ElemType x) {

//step 1:创建一个新的结点

Node *s = (Node*)malloc(sizeof(Node));

assert(s != NULL);

s->data = x;

s->next = NULL;

//step 2:定义指针p使其指向待插入位置的前一个结点

Node *p = list->first;//从头结点开始

while (p->next != NULL && p->next->data < s->data)

p = p->next;

//step 3:判断结点的待插入位置是否是表尾,若是则更新单链表的尾指针

if (p->next == NULL)

list->last = s;

//step 4:插入结点

s->next = p->next;

p->next = s;

//step 5:更新单链表长度

list->size++;

}

Node* find(List *list, ElemType x) {

//step 1:指针p指向单链表的第一个结点

Node *p = list->first->next;

//step 2:按照循环顺序查找链表结点

while (p != NULL && p->data != x)

p = p->next;

return p;

}

int length(List *list) {

return list->size;

}

void delete_val(List *list, ElemType x) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:确定结点在单链表中的位置,并判断其是否存在于单链表中

Node *p = find(list, x);

if (p == NULL) {

printf("要删除的数据不存在!\\n");

return;

}

//step 3:判断结点位置是否是表尾

if (p == list->last)//是表尾

pop_back(list);

else {//不是表尾

Node *q = p->next;

p->data = q->data;

p->next = q->next;

free(q);

list->size--;

}

}

void sort(List *list) {

//step 1:判断单链表中的结点数是否为0或1

if (list->size == 0 || list->size == 1) return;

//step 2:将单链表中第一个结点之后的链表部分截出,方便重新按顺序插入链表之中

Node *s = list->first->next; // 指针s指向单链表的第一个节点

Node *p = s->next;//q指向s后面的结点

list->last = s;//单链表的尾指针指向单链表的第一个结点

list->last->next = NULL;//截断链表

//step 3:将截出的链表中的结点根据其数据域大小重新插入到原来链表中

while (p != NULL) {

s = p;

p = p->next;

Node *q = list->first;

while (q->next != NULL && q->next->data < s->data)

q = q->next;

if (q->next == NULL)//判断q此时指向的是否是单链表的最后一个结点,若是则更新链表的尾指针

list->last = s;

//将结点重新插入链表

s->next = q->next;

q->next = s;

}

}

void reverse(List *list) {

//step 1:判断单链表中的结点数是否为0或1

if (list->size == 0 || list->size == 1) return;

//step 2:将单链表中第一个结点之后的链表部分截出,然后将截出的链表中的结点按头插法重新插入到原链表中

Node *p = list->first->next;

Node *q = p->next;

list->last = p;

list->last->next = NULL;

while (q != NULL) {

p = q;

q = q->next;

p->next = list->first->next;

list->first->next = p;

}

}

void clear(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:释放单链表中的每一个结点

Node *p = list->first->next;

while (p != NULL) {

list->first->next = p->next;

free(p);

p = list->first->next;

}

//step 3:头指针和尾指针重新都指向头结点

list->last = list->first;

//step 4:更新链表长度

list->size = 0;

}

void destroy(List *list) {

//step 1:清空单链表

clear(list);

//step 2:释放头结点

free(list->first);

//step 3:头指针和尾指针都赋值为空

list->first = list->last = NULL;

}

main.cpp

?

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
#include"slist.h"

void main() {

List mylist;

InitList(&mylist);

ElemType item;

Node *p = NULL;

int select = 1;

while (select) {

printf("*******************************************\\n");

printf("*[1] push_back [2] push_front *\\n");

printf("*[3] show_list [4] pop_back *\\n");

printf("*[5] pop_front [6] insert_val *\\n");

printf("*[7] find [8] length *\\n");

printf("*[9] delete_val [10] sort *\\n");

printf("*[11] reverse [12] clear *\\n");

printf("*[13*] destroy [0] quit_system *\\n");

printf("*******************************************\\n");

printf("请选择:>>");

scanf("%d", &select);

if (select == 0) break;

switch (select) {

case 1:

printf("请输入要插入的数据(-1结束):>");

while (scanf("%d", &item), item != -1) {

push_back(&mylist, item);

}

break;

case 2:

printf("请输入要插入的数据(-1结束):>");

while (scanf("%d", &item), item != -1) {

push_front(&mylist, item);

}

break;

case 3:

show_list(&mylist);

break;

case 4:

pop_back(&mylist);

break;

case 5:

pop_front(&mylist);

break;

case 6:

printf("请输入要插入的数据:>");

scanf("%d", &item);

insert_val(&mylist, item);

break;

case 7:

printf("请输入要查找的数据:>");

scanf("%d", &item);

p = find(&mylist, item);

if (p == NULL)

printf("要查找的数据在单链表中不存在!\\n");

break;

case 8:

printf("单链表的长度为%d\\n", length(&mylist));

break;

case 9:

printf("请输入要删除的值:>");

scanf("%d", &item);

delete_val(&mylist, item);

break;

case 10:

sort(&mylist);

break;

case 11:

reverse(&mylist);

break;

case 12:

clear(&mylist);

break;

//case 13:

//destroy(&mylist);

//break;

default:

printf("选择错误,请重新选择!\\n");

break;

}

}

destroy(&mylist); //程序结束,摧毁链表

}

附:单链表优化版本

slist.h

?

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
#ifndef __SLIST_H__

#define __SLIST_H__

#include<cstdio>

#include<malloc.h>

#include<assert.h>

typedef int ElemType;

typedef struct Node { //定义单链表中的结点信息

ElemType data; //结点的数据域

struct Node *next; //结点的指针域

}Node,*PNode;

typedef struct List { //定义单链表的链表信息

PNode first; //first指向单链表中的第一个结点

PNode last; //last指向单链表中的最后一个结点

size_t size; //记录单链表中的结点个数

}List;

void InitList(List *list);//初始化单链表

void push_back(List *list, ElemType x);//在单链表的末尾插入元素

void push_front(List *list, ElemType x);//在单链表的头部插入元素

void show_list(List *list);//打印单链表

void pop_back(List *list);//删除单链表的最后一个元素

void pop_front(List *list);//删除单链表的第一个元素

void insert_val(List *list, ElemType val);//将数据元素插入到单链表中(要求此时单链表中的数据元素顺序排列)

Node* find(List *list, ElemType x);//查找单链表中数据值为x的结点

int length(List *list);//求单链表的长度

void delete_val(List *list, ElemType x);//按值删除单链表中的某个数据元素

void sort(List *list);//对单链表进行排序

void reverse(List *list);//逆置单链表

void clear(List *list);//清除单链表

void destroy(List *list);//摧毁单链表

//代码优化

Node* CreateNode(ElemType x); //创建一个单链表结点

Node* begin(List *list); //返回单链表的第一个结点

Node* end(List *list); //返回单链表中最后一个结点的下一个结点

void insert(List *list, Node *pos, ElemType x); //在单链表的特定位置(pos)插入新的结点

#endif //__SLIST_H__

slist.cpp

?

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

184

185

186

187

188

189

190

191
#include"slist.h"

void InitList(List *list) {

list->first = list->last = (Node*)malloc(sizeof(Node)); //头结点

assert(list->first != NULL);

list->first->next = NULL;

list->size = 0;

}

//push_back的优化

void push_back(List *list, ElemType x) {

insert(list, end(list), x);

}

//push_front的优化

void push_front(List *list, ElemType x) {

insert(list, begin(list), x);

}

void show_list(List *list) {

//step 1:指针p指向单链表的第一个结点

Node *p = list->first->next;

//step 2:循环打印结点的信息

while (p != NULL) {

printf("%d->", p->data);

p = p->next;

}

printf("Nul.\\n");

}

void pop_back(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:定义指针p使其指向目标结点的前一个结点

Node *p = list->first;//从头结点开始

while (p->next != list->last)

p = p->next;

//step 3:删除目标结点

free(list->last);

list->last = p;

list->last->next = NULL;

//step 4:更新单链表的长度

list->size--;

}

void pop_front(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:定义指针p使其指向目标结点的前一个结点

Node *p = list->first->next;

//step 3:删除目标结点

list->first->next = p->next;

free(p);

//step 4:判断删除的结点是否是单链表的最后一个结点,若是则更新单链表的尾指针

if (list->size == 1)

list->last = list->first;

//step 4:更新单链表的长度

list->size--;

}

//insert_val的优化

void insert_val(List *list, ElemType x) {

//step 1:创建一个新的结点

Node *s = CreateNode(x);

//step 2:定义指针p使其指向待插入位置的前一个结点

Node *p = list->first;//从头结点开始

while (p->next != NULL && p->next->data < s->data)

p = p->next;

//step 3:判断结点的待插入位置是否是表尾,若是则更新单链表的尾指针

if (p->next == NULL)

list->last = s;

//step 4:插入结点

s->next = p->next;

p->next = s;

//step 5:更新单链表长度

list->size++;

}

Node* find(List *list, ElemType x) {

//step 1:指针p指向单链表的第一个结点

Node *p = list->first->next;

//step 2:按照循环顺序查找链表结点

while (p != NULL && p->data != x)

p = p->next;

return p;

}

int length(List *list) {

return list->size;

}

void delete_val(List *list, ElemType x) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:确定结点在单链表中的位置,并判断其是否存在于单链表中

Node *p = find(list, x);

if (p == NULL) {

printf("要删除的数据不存在!\\n");

return;

}

//step 3:判断结点位置是否是表尾

if (p == list->last)//是表尾

pop_back(list);

else {//不是表尾

Node *q = p->next;

p->data = q->data;

p->next = q->next;

free(q);

list->size--;

}

}

void sort(List *list) {

//step 1:判断单链表中的结点数是否为0或1

if (list->size == 0 || list->size == 1) return;

//step 2:将单链表中第一个结点之后的链表部分截出,方便重新按顺序插入链表之中

Node *s = list->first->next; // 指针s指向单链表的第一个节点

Node *p = s->next;//q指向s后面的结点

list->last = s;//单链表的尾指针指向单链表的第一个结点

list->last->next = NULL;//截断链表

//step 3:将截出的链表中的结点根据其数据域大小重新插入到原来链表中

while (p != NULL) {

s = p;

p = p->next;

Node *q = list->first;

while (q->next != NULL && q->next->data < s->data)

q = q->next;

if (q->next == NULL)//判断q此时指向的是否是单链表的最后一个结点,若是则更新链表的尾指针

list->last = s;

//将结点重新插入链表

s->next = q->next;

q->next = s;

}

}

void reverse(List *list) {

//step 1:判断单链表中的结点数是否为0或1

if (list->size == 0 || list->size == 1) return;

//step 2:将单链表中第一个结点之后的链表部分截出,然后将截出的链表中的结点按头插法重新插入到原链表中

Node *p = list->first->next;

Node *q = p->next;

list->last = p;

list->last->next = NULL;

while (q != NULL) {

p = q;

q = q->next;

p->next = list->first->next;

list->first->next = p;

}

}

void clear(List *list) {

//step 1:判断单链表是否为空

if (list->size == 0) return;

//step 2:释放单链表中的每一个结点

Node *p = list->first->next;

while (p != NULL) {

list->first->next = p->next;

free(p);

p = list->first->next;

}

//step 3:头指针和尾指针重新都指向头结点

list->last = list->first;

//step 4:更新链表长度

list->size = 0;

}

void destroy(List *list) {

//step 1:清空单链表

clear(list);

//step 2:释放头结点

free(list->first);

//step 3:头指针和尾指针都赋值为空

list->first = list->last = NULL;

}

//优化

Node* CreateNode(ElemType x) {

Node *s = (Node*)malloc(sizeof(Node));

assert(s != NULL);

s->data = x;

s->next = NULL;

return s;

}

Node* begin(List *list) {

return list->first->next;

}

Node* end(List *list) {

return list->last->next;

}

void insert(List *list, Node *pos, ElemType x) {

//step 1:创建一个新的结点

Node *s = CreateNode(x);

//step 2:确定带插入位置

Node *p = list->first;

while (p->next != pos)

p = p->next;

//step 3:插入结点

s->next = p->next;

p->next = s;

//step 4:判断结点是否插入到链表的表尾,若是则更新单链表的表尾指针

if (pos == NULL)

list->last = s;

//step 5:更新单链表长度

list->size++;

}

main.cpp

?

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
#include"slist.h"

void main() {

List mylist;

InitList(&mylist);

ElemType item;

Node *p = NULL;

int select = 1;

while (select) {

printf("*******************************************\\n");

printf("*[1] push_back [2] push_front *\\n");

printf("*[3] show_list [4] pop_back *\\n");

printf("*[5] pop_front [6] insert_val *\\n");

printf("*[7] find [8] length *\\n");

printf("*[9] delete_val [10] sort *\\n");

printf("*[11] reverse [12] clear *\\n");

printf("*[13*] destroy [0] quit_system *\\n");

printf("*******************************************\\n");

printf("请选择:>>");

scanf("%d", &select);

if (select == 0) break;

switch (select) {

case 1:

printf("请输入要插入的数据(-1结束):>");

while (scanf("%d", &item), item != -1) {

push_back(&mylist, item);

}

break;

case 2:

printf("请输入要插入的数据(-1结束):>");

while (scanf("%d", &item), item != -1) {

push_front(&mylist, item);

}

break;

case 3:

show_list(&mylist);

break;

case 4:

pop_back(&mylist);

break;

case 5:

pop_front(&mylist);

break;

case 6:

printf("请输入要插入的数据:>");

scanf("%d", &item);

insert_val(&mylist, item);

break;

case 7:

printf("请输入要查找的数据:>");

scanf("%d", &item);

p = find(&mylist, item);

if (p == NULL)

printf("要查找的数据在单链表中不存在!\\n");

break;

case 8:

printf("单链表的长度为%d\\n", length(&mylist));

break;

case 9:

printf("请输入要删除的值:>");

scanf("%d", &item);

delete_val(&mylist, item);

break;

case 10:

sort(&mylist);

break;

case 11:

reverse(&mylist);

break;

case 12:

clear(&mylist);

break;

//case 13:

//destroy(&mylist);

//break;

default:

printf("选择错误,请重新选择!\\n");

break;

}

}

destroy(&mylist); //程序结束,摧毁链表

}

希望本文所述对大家C语言程序设计有所帮助。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 C语言单链表实现方法详解 https://www.kuaiidc.com/73215.html

相关文章

猜你喜欢
发表评论
暂无评论