快速排序

快速排序的描述

像合并排序一样,快速排序也是基于分治模式的。下面是对一个典型子数组A[p..r]排序的分治过程的三个步骤。

  • 分解:数组A[p..r]被划分成两个(可能空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。下标q也在这个划分过程中进行计算。
  • 解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1, r]排序。
  • 合并:因为两个子数组是就地排序的,将它们的合并并不需要操作:这个数组A[p...r]已排序。

快速排序的实现

下面的过程实现快速排序:

QUICKSORT(A, p, r)
      if p < r
            then q <- PARTITION(A, p, r)
                     QUICKSORT(A, p, q-1)
                     QUICKSORT(A, q+1, r)

为排序一个完整的数组A,最初的调用是QUICKSORT(A, 1, length[A])。

int partition(int arg[], int p, int r)
{
	int tmp = arg[r];
	int i = p - 1;
	int j = 0;
	for (j = p; j < r; j++)
	{
		if (arg[j] <= tmp)
		{
			i = i + 1;
			swap(&arg[i], &arg[j]);
		}
	}
	swap(&arg[i + 1], &arg[r]);
	return i + 1;
}

数组划分

快速排序算法的关键是PARTITION过程,它对子数组A[p..r]进行就地重排。

PARTITION(A, p, r)
     x <- A[r]
     i <- p - 1
     for j <- p to r - 1
            do if A[j] <= x
                    then i <- i + 1
                          exchange A[i] <-> A[j]
     exchange A[i+1] <-> A[j]
     return i+1

C语言实现

void quicksort(int arg[], int p, int r)
{
	int q = 0;
	if (p >= r)
	{
		return;
	}
	else
	{
		q = partition(arg, p, r);
		quicksort(arg, p, q - 1);
		quicksort(arg, q + 1, r);
	}
}



思考:当数组A[p..r]中的元素均相同时,PARTITION返回的q值是多少?修改PARTITION,使得当数组A[p..r]中的所有元素的值相同时,q = [(q + r) / 2]。

答:返回的q值根据函数partition()的第八行来计算,如果是“小于等于”tmp,那么就返回r值,如果只是“小于”,那么就放回p值。

if (arg[j] <= tmp)


在调用partition后,左边的子数组和右边的子数组分别被递归排序。QuickSort中的第二次递归调用并不是必须的;可以用迭代控制结构代替它。这种技术称作为尾递归。考虑下面的这个快速排序的版本,它模拟了尾递归:

QUICKSROT'(A, p, r)
    while p < r
           do Partition and sort left subarray.
                 q <- PARTITION(A, p, r)
                 QUICKSORT'(A, p, q - 1)
                 p <- q + 1




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值