单链表的排序(快速排序与插入排序)

目录

单链表的快速排序

单链表的插入排序

单链表的快速排序

单链表的快速排序和数组的快排基本思想相同,同样是不断划分。(以从小到大排序为例)取一个结点设其为关键结点,将所有结点的数字与其比较,比关键结点数字大的放在结点的右边,比关键结点数字小的放在关键结点的左边。

单个排序为例(privot指针指向的为关键结点,p为与其比较的数字的结点,i指针指向所比较数字的上一个结点):

head435NULL
pr、ip
head345NUp
ppr、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的下一个结点的数字大于我们所要插入的结点数字时,进行插入操作。

刚开始head432NULL
指针位置prevlcurr
交换后head342NULL
currl

因为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;
	}
}

  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值