单链表的快速排序(转)

类似问题:荷兰国旗问题

      单链表的快速排序和数组的快速排序在基本细想上是一致的,以从小到大来排序单链表为例,都是选择一个支点,然后把小于支点的元素放到左边,把大于支点的元素放到右边。

      但是,由于单链表不能像数组那样随机存储,和数组的快排序相比较,还是有一些需要注意的细节:
  1. 支点的选取,由于不能随机访问第K个元素,因此每次选择支点时可以取待排序那部分链表的头指针。
  2. 遍历量表方式,由于不能从单链表的末尾向前遍历,因此使用两个指针分别向前向后遍历的策略实效,事实上,可以可以采用一趟遍历的方式将较小的元素放到单链表的左边。具体方法为:1)定义两个指针pslow, pfast,其中pslow指单链表头结点,pfast指向单链表头结点的下一个结点;2)使用pfast遍历单链表,每遇到一个比支点小的元素,就和pslow进行数据交换,然后令pslow=pslow->next。
  3. 交换数据方式,直接交换链表数据指针指向的部分,不必交换链表节点本身。
  4. pslow指的是比pivot小的那部分元素的最后一个元素。pfast指的是等待比较的那部分元素的第一个元素。

   基于上述思想的单链表快排序实现如下:

#include <iostream>
#include <ctime>
namespace std;
//单链表节点
strucusingt SList
{ 
	int data;
	struct SList* next;
};

void bulid_slist(SList** phead, int n)
{
	SList* ptr = NULL;
	for(int i = 0; i < n; ++i) {
		SList* temp = new SList;
		temp->data = rand() % n;
		temp->next = NULL;
		if(ptr == NULL) {
			*phead = temp; ptr = temp;
		}
		else {
			ptr->next = temp; ptr = ptr->next;
		}
	}
}

SList* get_last_slist(SList* phead)
{
	SList* ptr = phead;
	while(ptr->next)
		ptr = ptr->next;
	return ptr;
}

void print_slist(SList* phead)
{
	SList* ptr = phead;
	while(ptr)
	{
		printf("%d ", ptr->data);  
		ptr = ptr->next;
	}
	printf("\n");
}
void sort_slist(SList* phead, SList* pend)
{
	if(phead == NULL || pend == NULL) return;
	if(phead == pend) return;
	SList* pslow = phead;
	SList* pfast = phead->next;
	SList* ptemp = phead;
	while(pfast && pfast != pend->next)
	{
		if(pfast->data <= phead->data) //phead作为支点
		{
			ptemp = pslow;
			pslow = pslow->next;
			swap(pslow->data, pfast->data);
		}
		pfast = pfast->next;
	}
	swap(phead->data, pslow->data);
	sort_slist(phead, ptemp);//ptemp为左右两部分分割点的前一个节点
	sort_slist(pslow->next, pend);
}

void destroy_slist(SList* phead)
{
	SList* ptr = phead;
	while(ptr)
	{
		SList* temp = ptr;
		ptr = ptr->next;
		delete temp;
	}
}

int main(int argc, char** argv)
{
	srand(time(NULL));
	printf("sort single list\n");
	SList* phead = NULL;
	bulid_slist(&phead, 100);
	print_slist(phead);
	SList* plast = get_last_slist(phead);
	printf("head:%d, last:%d\n", phead->data, plast->data);
	sort_slist(phead, plast);
	print_slist(phead);
	destroy_slist(phead);
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值