快速排序法

快速排序

随便起个名字

一、定义:快速排序是一种基于分治法的排序算法,通过一次划分将待排序的序列分为两个子序列,其中一个子序列的元素都小于另一个子序列的元素,然后对两个子序列递归进行快速排序,直到所有的元素都有序。

二、过程:选择一个基准元素;

通过一遍遍历,将待排序的序列分成两个部分,一部分比基准元素小,另一部分比基准元素大或等于基准元素。

对这两部分分别递归进行快速排序;

合并结果。

一般有三种实现方法:

1.霍尔法:用pivot标记基准元素的下标(通常是数组的第一个元素),利用两个指针left和right分别指向数组的最左侧和最右侧,right指针先找比pivot基准元素小的元素,然后left找比pivot基准元素大的元素,找到后将两个数的位置交换,同时实现大数右移和小数左移,直到left和right相遇则排序完成,此时将pivot基准元素的下标返回给函数调用者就完成了单趟排序。

2.挖坑法:将pivot基准元素用变量单独保存,然后将pivot的位置空出来形成一个坑,left和right分别从左右两端向中心遍历,此时left先指向这个坑,right找到比pivot小的元素,找到后将该位置的元素直接放进坑里,并将自己空出来的位置设置为坑,left找比pivot大的元素,找到后将该元素放进坑里,并将现在空出来的位置设置为坑,一直遍历,直到left与right相遇,相遇的位置一定为坑(left和right一定有一个指向坑),此时将pivot基准元素放进坑内,并返回基准元素下标完成单趟排序。

3. 前后指针法。

注:还可以使用非递归的方式实现,如栈储存。

如果基准元素pivot选择的是数组中最大或最小的数值,则快速排序的递归深度会非常深,排序效率会很低。

三、选择基准元素的方法:

1.随机选择:利用rand函数随机选择数组中的一个数作为随机数,但是仍然有概率选到最大值或最小值。

2.选中间位置:选取左右下标的中间下标作为基准元素,这种方法对于有序数组可以达到最大效率,但是无序数组仍可能选到最大值或最小值。

3.三值取中:在left、right和中间下标的值中选取一个折中值,基准元素不可能为最大值或最小值(若数组中的元素未出现重复)。

四、快速排序程序:

void quick_sort(int a[], int low, int high) {
int i = low;
int j = high;
int key = a[i];
while (i < j) {
    while (i < j && a[j] >= key) {
        j--;
    }
    a[i] = a[j];
    while (i < j && a[i] <= key) {
        i++;
    }
    a[j] = a[i];
}
a[i] = key;
if (i - 1 > low) {
    quick_sort(a, low, i - 1);
}
if (i + 1 < high) {
    quick_sort(a, i + 1, high);
}

}

或者

void exchange(int a[], int b, int c)
{
	int t;
	t=a[b];
	a[b]=a[c];
	a[c]=t;
}

void quick_sort(int a[], int low, int high) {
    int i = low;
    int j = high;
    int key = a[i];
    while (i < j) {
        while (i < j && a[j] >= key) {
            j--;
        }
        exchange(a, i, j);
        //a[i] = a[j];
        while (i < j && a[i] <= key) {
            i++;
        }
        //a[j] = a[i];
        exchange(a, i, j);
    }
	//a[i]=key;
    if (i - 1 > low) {
        quick_sort(a, low, i - 1);
    }
    if (i + 1 < high) {
        quick_sort(a, i + 1, high);
    }
}

或者:

void quicksort(int a[], int left, int right) {
int i = left, j = right;//i和j分别是左和右的指针的下标
int mid = a[(left + right) / 2];//取数组中间位置为基准值
while (i <= j) //当左指针在右指针的左侧时进行
{
    while (a[i] < mid) i++;//当左边小于基准值时,向左继续比较
    while (a[j] > mid) j--;//当右边大于基准值时,向右继续比较
    if (i <= j) //此时左指针到达大于基准值处,右指针到达小于基准值处
    {
    	int t;
		t=a[i];
		a[i]=a[j];
		a[j]=t;
		//交换左右指针当前位置的数值,使得小于基准值的数移到基准值位置的左边,大于基准值的数移到基准值位置的右边
        i++;
        j--;
        //交换完成后,左指针向右移动,右指针向左移动
    }
}
if (left < j) quicksort(a, left, j);
//若右指针最后大于最左位置,则在基准值的左边再次进行排序
if (i < right) quicksort(a, i, right);
//若左指针最后小于最右位置,则在基准值的右边再次进行排序
//递归

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值