十大排序算法之快速排序6

6、快速排序(Quick Sort)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

6.1 算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

6.2 图例演示

                    【1】https://blog.csdn.net/MoreWindows/article/details/6684558

                    【2】https://blog.csdn.net/zpznba/article/details/83745205

        这两种思路解法都很棒。

6.3 代码实现

  版本1:挖坑填数

//挖坑的代码
int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
	int i = l, j = r;
	int x = s[l]; //s[l]即s[i]就是第一个坑
	while (i < j)
	{
		// 从右向左找小于x的数来填s[i]
		while(i < j && s[j] >= x) 
			j--;  
		if(i < j) 
		{
			s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
			i++;
		}
 
		// 从左向右找大于或等于x的数来填s[j]
		while(i < j && s[i] < x)
			i++;  
		if(i < j) 
		{
			s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
			j--;
		}
	}
	//退出时,i等于j。将x填到这个坑中。
	s[i] = x;
 
	return i;
}
//分治的代码
void quick_sort1(int s[], int l, int r)
{
	if (l < r)
    {
		int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
		quick_sort1(s, l, i - 1); // 递归调用 
		quick_sort1(s, i + 1, r);
	}
}

  版本2: 

//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
		//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
				j--;  
            if(i < j) 
				s[i++] = s[j];
			
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
				i++;  
            if(i < j) 
				s[j--] = s[i];
        }
        s[i] = x;

        quick_sort(s, l, i - 1); // 递归调用 
        quick_sort(s, i + 1, r);
    }
}
  •   版本3:(Parition函数很重要,有很多用处!!!)重点掌握这种解法
#include<iostream>
 
using namespace std;
 
int Parition(int a[], int low,int high){
    int pivot=a[high];
    int i=low;       //分区的点, a[low...i...high],i左边的数(不包含i)小于high,i右边的数大于high,然后将i位置的数和high的位置交换,
    for(int j=low;j<high;++j)
    {
        //j指向当前遍历元素,如果大于等于pivot,继续向前
        //如果小于当前元素,则和i指向的元素交换
        if (a[j]<pivot) {
            swap(a[j], a[i]);
            i++;
        }
    }
    swap(a[i], a[high]);
    return i;
    
}
 
void QuickSort(int a[], int low, int high){
    if(low<high)
    {
        int q=Parition(a,low, high);
        QuickSort(a, low, q-1);
        QuickSort(a, q+1,high);
        
    }
    
}
 
int main(){
    int a[8] = {3,1,2,4,5,8,7,6};
    QuickSort(a,0,7);
    for(int i=0;i<8;++i)
        cout<<a[i]<<" ";
}

参考文献:【1】https://blog.csdn.net/MoreWindows/article/details/6684558

                 【2】https://blog.csdn.net/zpznba/article/details/83745205

                 【3】https://blog.csdn.net/k_koris/article/details/80585979  很详细的参考图!!!

快排的非递归版本: 重要!!!

                 【4】https://blog.csdn.net/qq_36528114/article/details/78667034

非递归实现

递归的算法主要是在划分子区间,如果要非递归实现快排,只要使用一个栈来保存区间就可以了。
一般将递归程序改成非递归首先想到的就是使用栈,因为递归本身就是一个压栈的过程。

void QuickSort(int* array,int left,int right)
{
	assert(array);
	stack<int> s;
	s.push(left);
	s.push(right);//后入的right,所以要先拿right
	while(!s.empty)//栈不为空
	{
		int right = s.top();
		s.pop();
		int left = s.top();
		s.pop();
		
		int index = PartSort(array,left,right);
		if((index - 1) > left)//左子序列
		{
			s.push(left);
			s.push(index - 1);
		}
		if((index + 1) < right)//右子序列
		{
			s.push(index + 1);
			s.push(right);
		}
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值