单链表排序方法
来源:互联网 发布:淘宝该版本不支持授权 编辑:程序博客网 时间:2024/06/01 09:37
单链表排序是单链表的常见编程任务之一,也是面试中经常出现的题目。单链表排序的关键是交换算法,需要额外考虑。选择排序是比较直观的排序算法之一,这里就使用选择排序实现单链表的排序。
如果需要对选择排序复习一下,传送门:算法导论:选择排序的原理与实现。
C实现代码如下:
01
LinkList SelectSort2(LinkList L)
02
{
03
LinkList p,q,small;
04
int
temp;
05
06
for
(p = L->next; p->next != NULL; p = p->next)
07
{
08
small = p;
09
for
(q = p->next; q; q = q->next)
10
{
11
if
(q->data < small->data)
12
{
13
small = q;
14
}
15
}
16
printf
(
"循环后,获得最小值为:%d, 此时链表为:"
, small->data);
17
if
(small != p)
18
{
19
temp = p->data;
20
p->data = small->data;
21
small->data = temp;
22
}
23
ListTraverse(L);
24
}
25
printf
(
"输出排序后的数字:\n"
);
26
return
L;
27
}
或者
01
LinkList SelectSort(LinkList L)
02
{
03
LinkList first;
/*排列后有序链的表头指针*/
04
LinkList tail;
/*排列后有序链的表尾指针*/
05
LinkList p_min;
/*保留键值更小的节点的前驱节点的指针*/
06
LinkList min;
/*存储最小节点*/
07
LinkList p;
/*当前比较的节点*/
08
09
first = NULL;
10
while
(L != NULL)
/*在链表中找键值最小的节点。*/
11
{
12
/*注意:这里for语句就是体现选择排序思想的地方*/
13
for
(p=L,min=L; p->next!=NULL; p=p->next)
/*循环遍历链表中的节点,找出此时最小的节点。*/
14
{
15
if
(p->next->data < min->data)
/*找到一个比当前min小的节点。*/
16
{
17
p_min = p;
/*保存找到节点的前驱节点:显然p->next的前驱节点是p。*/
18
min = p->next;
/*保存键值更小的节点。*/
19
}
20
}
21
22
/*上面for语句结束后,就要做两件事;
23
一是把它放入有序链表中;
24
二是根据相应的条件判断,安排它离开原来的链表。*/
25
26
/*第一件事*/
27
if
(first == NULL)
/*如果有序链表目前还是一个空链表*/
28
{
29
first = min;
/*第一次找到键值最小的节点。*/
30
tail = min;
/*注意:尾指针让它指向最后的一个节点。*/
31
}
32
else
/*有序链表中已经有节点*/
33
{
34
tail->next = min;
/*把刚找到的最小节点放到最后,即让尾指针的next指向它。*/
35
tail = min;
/*尾指针也要指向它。*/
36
}
37
/*第二件事*/
38
if
(min == L)
/*如果找到的最小节点就是第一个节点*/
39
{
40
//printf("表头%d已经是最小,当前结点后移。\n", min->data);
41
L = L->next;
/*显然让head指向原head->next,即第二个节点,就OK*/
42
}
43
else
/*如果不是第一个节点*/
44
{
45
p_min->next = min->next;
/*前次最小节点的next指向当前min的next,这样就让min离开了原链表。*/
46
}
47
}
48
if
(first != NULL)
/*循环结束得到有序链表first*/
49
{
50
tail->next = NULL;
/*单向链表的最后一个节点的next应该指向NULL*/
51
}
52
L = first;
53
return
L;
54
}
完整的可执行程序:
001
#include "stdio.h"
002
003
#define OK 1
004
#define ERROR 0
005
#define TRUE 1
006
#define FALSE 0
007
008
typedef
int
Status;
/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
009
typedef
int
ElemType;
/* ElemType类型根据实际情况而定,这里假设为int */
010
011
typedef
struct
Node
012
{
013
ElemType data;
014
struct
Node *next;
015
} Node;
016
typedef
struct
Node *LinkList;
/* 定义LinkList */
017
018
Status visit(ElemType c)
019
{
020
printf
(
"->%d"
,c);
021
return
OK;
022
}
023
024
/* 初始化顺序线性表 */
025
Status InitList(LinkList *L)
026
{
027
*L=(LinkList)
malloc
(
sizeof
(Node));
/* 产生头结点,并使L指向此头结点 */
028
if
(!(*L))
/* 存储分配失败 */
029
return
ERROR;
030
(*L)->next=NULL;
/* 指针域为空 */
031
032
return
OK;
033
}
034
035
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
036
int
ListLength(LinkList L)
037
{
038
int
i=0;
039
LinkList p=L->next;
/* p指向第一个结点 */
040
while
(p)
041
{
042
i++;
043
p=p->next;
044
}
045
return
i;
046
}
047
048
/* 初始条件:顺序线性表L已存在 */
049
/* 操作结果:依次对L的每个数据元素输出 */
050
Status ListTraverse(LinkList L)
051
{
052
LinkList p=L->next;
053
while
(p)
054
{
055
visit(p->data);
056
p=p->next;
057
}
058
printf
(
"\n"
);
059
return
OK;
060
}
061
062
/* 随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */
063
void
CreateListTail(LinkList *L,
int
n)
064
{
065
LinkList p,r;
066
int
i;
067
srand
(
time
(0));
/* 初始化随机数种子 */
068
*L = (LinkList)
malloc
(
sizeof
(Node));
/* L为整个线性表 */
069
r=*L;
/* r为指向尾部的结点 */
070
for
(i=0; i < n; i++)
071
{
072
p = (Node *)
malloc
(
sizeof
(Node));
/* 生成新结点 */
073
p->data =
rand
()%100+1;
/* 随机生成100以内的数字 */
074
r->next=p;
/* 将表尾终端结点的指针指向新结点 */
075
r = p;
/* 将当前的新结点定义为表尾终端结点 */
076
}
077
r->next = NULL;
/* 表示当前链表结束 */
078
}
079
080
LinkList SelectSort2(LinkList L)
081
{
082
LinkList p,q,small;
083
int
temp;
084
085
for
(p = L->next; p->next != NULL; p = p->next)
086
{
087
small = p;
088
for
(q = p->next; q; q = q->next)
089
{
090
if
(q->data < small->data)
091
{
092
small = q;
093
}
094
}
095
printf
(
"循环后,获得最小值为:%d, 此时链表为:"
, small->data);
096
if
(small != p)
097
{
098
temp = p->data;
099
p->data = small->data;
100
small->data = temp;
101
}
102
ListTraverse(L);
103
}
104
printf
(
"输出排序后的数字:\n"
);
105
return
L;
106
}
107
108
LinkList SelectSort(LinkList L)
109
{
110
LinkList first;
/*排列后有序链的表头指针*/
111
LinkList tail;
/*排列后有序链的表尾指针*/
112
LinkList p_min;
/*保留键值更小的节点的前驱节点的指针*/
113
LinkList min;
/*存储最小节点*/
114
LinkList p;
/*当前比较的节点*/
115
116
first = NULL;
117
while
(L != NULL)
/*在链表中找键值最小的节点。*/
118
{
119
/*注意:这里for语句就是体现选择排序思想的地方*/
120
for
(p=L,min=L; p->next!=NULL; p=p->next)
/*循环遍历链表中的节点,找出此时最小的节点。*/
121
{
122
if
(p->next->data < min->data)
/*找到一个比当前min小的节点。*/
123
{
124
p_min = p;
/*保存找到节点的前驱节点:显然p->next的前驱节点是p。*/
125
min = p->next;
/*保存键值更小的节点。*/
126
}
127
}
128
129
/*上面for语句结束后,就要做两件事;
130
一是把它放入有序链表中;
131
二是根据相应的条件判断,安排它离开原来的链表。*/
132
133
/*第一件事*/
134
if
(first == NULL)
/*如果有序链表目前还是一个空链表*/
135
{
136
first = min;
/*第一次找到键值最小的节点。*/
137
tail = min;
/*注意:尾指针让它指向最后的一个节点。*/
138
}
139
else
/*有序链表中已经有节点*/
140
{
141
tail->next = min;
/*把刚找到的最小节点放到最后,即让尾指针的next指向它。*/
142
tail = min;
/*尾指针也要指向它。*/
143
}
144
/*第二件事*/
145
if
(min == L)
/*如果找到的最小节点就是第一个节点*/
146
{
147
//printf("表头%d已经是最小,当前结点后移。\n", min->data);
148
L = L->next;
/*显然让head指向原head->next,即第二个节点,就OK*/
149
}
150
else
/*如果不是第一个节点*/
151
{
152
p_min->next = min->next;
/*前次最小节点的next指向当前min的next,这样就让min离开了原链表。*/
153
}
154
}
155
if
(first != NULL)
/*循环结束得到有序链表first*/
156
{
157
tail->next = NULL;
/*单向链表的最后一个节点的next应该指向NULL*/
158
}
159
L = first;
160
return
L;
161
}
162
163
int
main()
164
{
165
LinkList L;
166
Status i;
167
char
opp;
168
ElemType e;
169
int
find;
170
int
tmp;
171
172
i=InitList(&L);
173
printf
(
"初始化L后:ListLength(L)=%d\n"
,ListLength(L));
174
175
printf
(
"\n1.查看链表 \n2.创建链表(尾插法) \n3.链表长度 \n4.交换两个结点 \n0.退出 \n请选择你的操作:\n"
);
176
while
(opp !=
'0'
)
177
{
178
scanf
(
"%c"
,&opp);
179
switch
(opp)
180
{
181
case
'1'
:
182
ListTraverse(L);
183
printf
(
"\n"
);
184
break
;
185
186
case
'2'
:
187
CreateListTail(&L,10);
188
printf
(
"整体创建L的元素(尾插法):\n"
);
189
ListTraverse(L);
190
printf
(
"\n"
);
191
break
;
192
193
case
'3'
:
194
//clearList(pHead); //清空链表
195
printf
(
"ListLength(L)=%d \n"
,ListLength(L));
196
printf
(
"\n"
);
197
break
;
198
199
case
'4'
:
200
L = SelectSort2(L);
201
//printf("%d \n", find);
202
ListTraverse(L);
203
printf
(
"\n"
);
204
break
;
205
206
case
'0'
:
207
exit
(0);
208
}
209
}
210
}
0 0
- 单链表常见排序方法
- 单链表排序方法
- Java单链表排序方法
- 算法-单链表排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- 排序方法
- JavaMail(JAVA邮件服务) API详解
- 在iOS 8中使用UIAlertController
- DLL 基于IHE ITI-ATNA技术规范的区域医疗信息共享安全问题解决方案
- Android Studio系列教程四--Gradle基础
- UIButton: set image for selected-highlighted state
- 单链表排序方法
- 获取当天的年,月,日,星期。
- Easy Game
- 网站制作笔记二之建站工具和准备
- java日常小笔记
- C语言:day12~通讯录
- [Elasticsearch]查询语法速查
- <iOS>AFNetworking使用介绍
- 【Java开发】--jdom解析xml-创建xml