【数据结构】单链表比第一个元素大的放在前面,其他放在后面
题目
一单链表,以第一个元素为基准,将小于该元素的结点全部放到前面,大于该结点的元素全部放到后面。时间复杂度要求为O(n),不能申请新空间。
分析
将所有小于第一个元素m的元素移到m前面去,则遍历单链表,比m小的用头插法放到L后面,比m大的则不做改动
解题思路
有几个函数? 1. 初始化链表 2. 创建单链表 3. 输出单链表 4. 改变单链表(本次程序的关键)
改变单链表函数怎么写?
重复一下,改变单链表函数的功能是:遍历单链表,比第一个元素小的用头插法放到L后面,比m大的则不做改动 。
设置几个指针,用来进行操作:
* p1:指向单链表的第一个结点,用来提取第一个元素的值
* p:当前遍历的结点
* pre:当前遍历节点的前一个结点
* q:当前遍历节点的后一个结点
逻辑思路:
1 先用p1指向单链表的第一个结点
2 pre指向第一个结点,p指向第二个结点,q指向第三个结点,开始遍历
3 如果p->data < p1->data,即当前结点小于第一个元素,用头插法把当前结点移到头结点的后面.
4 如果p->data >= p1->data,即当前结点大于等于第一个元素,则不做改动,pre, p, q继续往后。
具体代码如下:
while(p
){
q
=p
->next
;
if(p
->data
< p1
->data
){
pre
->next
= p
->next
;
p
->next
= L
->next
;
L
->next
= p
;
p
=q
;
}
else{
pre
= p
;
p
= p
->next
;
}
}
我的代码
#include<stdio.h>
#include<stdlib.h>
typedef int Elem
;
typedef struct Node
{
Elem data
;
struct Node
*next
;
}*Linklist
, Node
;
void Init(Linklist
*);
void Create(Linklist
);
void output(Linklist
);
void change(Linklist
);
int main(){
system("color 3F");
Linklist L
;
Init(&L
);
printf("\t\t\t请输入单链表L的元素(结束则输入-1):");
Create(L
);
printf("\t\t\t此时L单链表元素为:");
output(L
);
change(L
);
printf("\t\t\t合并后L单链表元素为:");
output(L
);
}
void Init(Linklist
*L
){
*L
= (Linklist
)malloc(sizeof(Node
));
(*L
)->next
= NULL;
}
void Create(Linklist L
){
Node
*r
, *s
;
int flag
= 1;
r
= L
;
Elem c
;
while(flag
){
scanf("%d", &c
);
if(c
!=-1){
s
= (Linklist
)malloc(sizeof(Node
));
s
->data
= c
;
r
->next
= s
;
r
= s
;
}
else{
flag
= 0;
r
->next
= NULL;
}
}
}
void output(Linklist L
){
Node
*r
;
r
= L
->next
;
while(r
){
printf("%d ", r
->data
);
r
= r
->next
;
}
printf("\n");
}
void change(Linklist L
){
if(L
->next
== NULL) return;
Node
*p
, *q
, *p1
, *pre
;
p1
= L
->next
;
p
= p1
->next
;
pre
= p1
;
while(p
){
q
=p
->next
;
if(p
->data
< p1
->data
){
pre
->next
= p
->next
;
p
->next
= L
->next
;
L
->next
= p
;
p
=q
;
}
else{
pre
= p
;
p
= p
->next
;
}
}
}