快速排序的注意点

//划分排序
public int partionIt(int low,int upper)//数组上界与下界
	{
		int left=low;//left为左指针
		int right=upper;//right为右指针
		int pivot=a[upper];//pivot为中心点
		while(true)
		{
			while(a[left]<pivot) //注意不能等于,图像说明情况
				left++;          //若左指针所指向的数组元素小于中心点,则左指针右移
			while(a[right]>pivot)//注意不能等于,图像说明情况
				right--;         //若右指针所指向的数组元素大于中心点,则右指针左移
			if(left==right)      //代表遍历结束,即时间复杂度为O(upper-low)
				return left;     //也可以写return right
			if(a[left]==a[right])//防止两个数永无止境的交换
			left++;              //也可以right++
			else
			{
			int temp=a[left];    //交换
			a[left]=a[right];
			a[right]=temp;
			}
		}
	}

 

此时left指向5,right指向9,pivot为9。left当指向12时由于比9大于则left锁定12。我们注意到刚才强调的不能等于,则right一开始就锁定了9,即12与9互换位置,如下图所示:

 

由于9等于pivot,所以left锁定了9,而right当从12右边遍历到9等于pivot则锁定了9。我们应该注意到一个问题由于pivot为9,a[left]<pivot,a[right]>pivot的原因,所以总会有一个指针指向9,即left没有遍历就锁定了9,而right当指向9由于不符合a[right]>pivot的条件跳出whlie循环锁定了9。如下图所示:

 

 如果我们删去这两行代码

 则会导致交换完之后left,right又再次锁定各自的9,又交换,不断循环下去不断交换。注意我们前言提到:

所以此时我们让left++或者right++则跳出死循环,如图所示:

则出现如下情况:

 

 

此时 left和right相等,且以划分好数组,即left与right都指向了9,9也为pivot中心点。,我们返回pivot。

注意左遍历右遍历到同一个点,不会出现left>=right,只会出现left和right相等,也符合我们的逻辑思维,左遍历与右遍历到一个点,即遍历一次!时间复杂度为0(n)。

则我们代码为:

 接着我们基于划分排序,利用递归实现快速排序。

public void quickSort(int low,int upper)
{
//我们在划分左半数组和右半数组时,可能出现数组只有一个数,或者数组压根就没有数了,所以是low>=upper
		if(low >= upper)
        {
			return;
		}
		int pivotIdx = partionIt(low, upper);//pivotIdx所得到的值即我们前言所说的中点值
		// 我们将中点值往左划分为左半数组quickSort
		quickSort(low, pivotIdx - 1);
		
		// 我们将中点值往右划分为右半数组quickSort
		quickSort(pivotIdx+1, upper);
}

 

如图所示给一个数组

则最终为:

 即划分排序中返回left,此时我们获取到了pivot的下标。

根据这几行代码。

将数组划分为左右,我们不考虑将pivot的值划分到左数组或者右数组,这符合逻辑思维,也可以让划分排序少一个数。如图所示

 

 我们先分析左数组,左数组中只有一个元素则return。

再分析右数组,如图所示:

 最终结果为:

 我们注意到中点值划分左右,右数组是没数的

// 我们将中点值往右划分为右半数组quickSort
        quickSort(pivotIdx+1, upper); 

注意pivotdx+1比upper大一个值

所以我们在实现代码时候是

if(low >= upper)
  {
      return;
  }

不能只写low==upper,否则会导致运行错误。应该得包含low>upper

最后数组结果为:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值