目录
单链表的快速排序
单链表的快速排序和数组的快排基本思想相同,同样是不断划分。(以从小到大排序为例)取一个结点设其为关键结点,将所有结点的数字与其比较,比关键结点数字大的放在结点的右边,比关键结点数字小的放在关键结点的左边。
单个排序为例(privot指针指向的为关键结点,p为与其比较的数字的结点,i指针指向所比较数字的上一个结点):
head | 4 | 3 | 5 | NULL |
pr、i | p | |||
head | 3 | 4 | 5 | NUp |
p | pr、i |
此链表设4为关键节点,3比4小因此应该放在4的左边,因此交换两节点的位置。交换结点的代码如下:
if(privot->val > p->val)
{
i->next = p->next;
p->next = head->next;
head->next = p;
}
交换后则p应该向前移一位,此时p与pr结点相同,不符合以上交换条件,则指针位置并不改变,但由于循环会使p向后移一位,因此在不交换结点时,应该让i指针向后移一位。
以此类推,当此次循环结束可知关键结点左边都比它小,右边都比它大,即关键结点的位置确定了。因此使关键结点左边与右边分成两半,分别以同样的方式排序,即进入递归。通过递归排序完成。
单链表的快速排序代码如下:
#include<stdio.h>
#include<stdlib.h>
struct stu
{
int val;
struct stu *next;
};
struct stu *partition(struct stu *head, struct stu *tail)
{
struct stu *p, *i, *privot;
privot = head->next;
for(i = privot, p = privot->next; p && p != tail; p = i->next)
{
if(privot->val > p->val)
{
i->next = p->next;
p->next = head->next;
head->next = p;
}
else
{
i = i->next;
}
}
return privot;
}
void Quick_Sort(struct stu *head, struct stu *tail)
{
if(!head || head->next == tail || head->next->next == tail)
{
return ;
}
struct stu *privot = partition(head, tail);
Quick_Sort(head, privot);
Quick_Sort(privot, tail);
}
int main()
{
int n, i;
scanf("%d",&n);
struct stu *head = (struct stu *)malloc(sizeof(struct stu));
struct stu *tail, *s;
tail = head;
for(i = 0; i < n; i++)
{
struct stu *p = (struct stu *)malloc(sizeof(struct stu));
scanf("%d",&p->val);
tail->next = p;
tail = p;
}
tail->next = NULL;
tail = NULL;
Quick_Sort(head, tail);
s = head->next;
for(i = 0; i < n; i++)
{
printf("%d ",s->val);
s = s->next;
}
}
单链表的插入排序
(以从小到大为例)插入排序为以第二个数字开始,将每一个数字插入到比它小的数字之前,curr指针所指向的为被插入的结点位置,与前一个结点进行比较,如果它比前一个结点数字小即代表它需要插入。进入内层循环,prev所指向的结点为插入位置的前一个结点,当prev的下一个结点的数字大于我们所要插入的结点数字时,进行插入操作。
刚开始 | head | 4 | 3 | 2 | NULL |
指针位置 | prev | l | curr | ||
交换后 | head | 3 | 4 | 2 | NULL |
curr | l |
因为3比4小因此将3进行插入操作。插入时应先时prev位于头结点位置,进行循环,找到插入点。
插入操作代码如下:
struct stu *prev = head;
while(prev->next->val <= curr->val)
{
prev = prev->next;
}
l->next = curr->next;
curr->next = prev->next;
prev->next = curr;
如果curr指向的数字比l指向的数字大,无需插入,则使两个指针都向后移,若出现了插入操作只需使curr放在l的后一个结点。
单链表的插入排序代码如下:
#include<stdio.h>
#include<stdlib.h>
struct stu
{
int val;
struct stu *next;
};
int main()
{
int n, i;
scanf("%d",&n);
struct stu *head = (struct stu *)malloc(sizeof(struct stu));
struct stu *tail, *s;
tail = head;
for(i = 0; i < n; i++)
{
struct stu *p = (struct stu *)malloc(sizeof(struct stu));
scanf("%d",&p->val);
tail->next = p;
tail = p;
}
tail->next = NULL;
tail = NULL;
struct stu *l = head->next;
struct stu *curr = head->next->next;
while(curr != NULL)
{
if(l->val <= curr->val)
{
l = l->next;
}
else
{
struct stu *prev = head;
while(prev->next->val <= curr->val)
{
prev = prev->next;
}
l->next = curr->next;
curr->next = prev->next;
prev->next = curr;
}
curr = l->next;
}
s = head->next;
for(i = 0; i < n; i++)
{
printf("%d ",s->val);
s = s->next;
}
}