单链表快排

在单链表上实现快排,需要考虑以下几个因素:

  • 单链表存取随机结点需要从头遍历
  • 指针单向,取前驱结点需要从头遍历
  • 不能像数组那样以下标判断越界
因此,我们使用一趟排序中的策略三,其好处是:只要维护足够多(实际上也并不多)的指针,就能只遍历一次即完成一趟排序
但和数组快排不同的是:
  • 为了方便,不使用三数中值分割法选取pivot(需要遍历一次链表),而直接使用当前子链表的第一个结点作为pivot。这样性能肯定受到影响
  • 在一趟排序中,pivot被放置在最左端,最后和div-1交换(因为放置在最右端同样需要遍历一次链表)

代码如下:
typedef struct node{
	int data;
	struct node * next;
} Node;

void swap(int * a, int * b){
	assert(a != NULL);
	assert(b != NULL);
	if(a != b){
		*a ^= *b;
		*b ^= *a;
		*a ^= *b;
	}
}

void linklist_qsort(Node * left, Node * right){
	assert(left != NULL);
	assert(right != NULL);
	if(left != right){
		Node * pivot, * div, * div_prior, * div_prior_prior, * p;  //div_piror用于一趟排序最后和pivot交换,div_prior_prior用于表示左子链表的右边界(用于递归和越界判断)
		pivot = left;
		div_prior = left;
		p = left->next;
		div = left->next;
		div_prior_prior = NULL;
		while(p != right->next){
			if(p->data < pivot->data){
				swap(&p->data, &div->data);
				div_prior_prior = div_prior;
				div_prior = div;
				div = div->next;
			}
			p = p->next;
		}
		swap(&pivot->data, &div_prior->data);
		if(div_prior_prior != NULL)  //若pivot在最左端,跳过
			linklist_qsort(left, div_prior_prior);
		if(div_prior != right)  //若pivot在最右端,跳过
			linklist_qsort(div, right);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值