【算法】快速排序

注:该篇文章已与我的个人博客同步更新。欢迎移步https://cqh-i.github.io/体验更好的阅读效果。

快速排序的思想

快速排序通过将一个数组划分成两个子数组, 然后通过递归调用自身为每一个子数组进行快速排序来实现.

如何进行划分

设定关键字(基准数), 将比关键字小的放在一组, 比关键字大的放在另一组.
下面将以数组[6,1,2,7,9,3,4,5,10,8]为例, 演示排序过程

步骤

  1. 先把数组中的一个数当做基准数, 一般会把数组中最左边的数当做基准数, 然后从两边进行检索. 先从数组的右边检索比基准数小的, 再从左边检索比基准数大的. 如果检索到了, 就停下, 然后交换这两个元素, 然后再继续检索.在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  2. i和j一旦相遇, 就停止检索, 把基准数和相遇位置的元素交换
    在这里插入图片描述
  3. 基准数和相遇位置的元素交换完成后, 表示第一轮排序结束, 此时数组的特点: 基准数左边的元素都比它小, 右边的元素都比它大.在这里插入图片描述
  4. 接下来, 先排基准数左边的数组, 排完之后再排基准数右边的数组, 方式和第一轮一样, 整个过程如下图
    在这里插入图片描述

时间复杂度

最坏:O(n^2)
平均: O(nlogn)

稳定性

不稳定, 比如序列为 (5, 3, 3, 4, 3, 8, 9, 10, 11), 第一轮中, 基准数5和第5位置的3交换, 就会破坏稳定性

Java版代码

public class QuickSort {
   /**   
    * @Description: 快速排序
    * @param arr 待排序的数组
    * @param left 从什么位置开始排序
    * @param right  排到哪个位置
    * @return: void      
    */
   public static void quickSort(int[] arr, int left, int right) {
       // 数组合法性检测, 递归出口
       if (left > right)
           return;
       // 定义基准数
       int base = arr[left];
       // 定义变量i, 指向最左边
       int i = left;
       // 定义变量j, 指向最右边
       int j = right;

       // 当i和j不相遇的时候, 在循环中检索
       while (i != j) {
           // 向量j从右往左检索比基准数小的, 如果检索到比基准数小的, 就停下.
           while (arr[j] >= base && i < j) {
               j--; // j从右往左移动
           }
           // i 从左往右检索
           while (arr[i] <= base && i < j) {
               i++; // i 从左往右移动
           }

           // i停下了, j也停下, 交换两个位置的元素
           int temp = arr[i];
           arr[i] = arr[j];
           arr[j] = temp;
       }

       // 如果i和j相遇了, 就交换基准数和相遇位置的元素
       arr[left] = arr[i];
       arr[i] = base;

       // 基准数在这里就归位了, 左边的数字都比它小, 右边的数字都比它大.
       // 排基准数左边的数组
       quickSort(arr, left, i - 1);
       // 排基准数右边的数组
       quickSort(arr, j + 1, right);
   }

   public static void main(String[] args) {
       int[] arr = new int[] { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 };
       quickSort(arr, 0, arr.length - 1);
       System.out.println(Arrays.toString(arr));
   }
}

C语言版

int Partition(int L[], int low, int high)//对子表进行一趟排序,返回枢轴位置
{//L[0]闲置或用作哨兵单元 
	L[0] = L[low];
	int pivotkey = L[low];
	while(low < high)
	{
		while(low < high && L[high] >= pivotkey) --high;
		L[low] = L[high];
		while(low < high && L[low] <= pivotkey) ++low;
		L[high] = L[low];
	}
	L[low] = L[0];
	return low;
}
void Qsort(int L[], int low, int high)
{//L[0]闲置,调用前置初值 low = 1, high = L的length;
	if(low < high)
	{
		int pivotloc = Partition(L, low ,high);//pivotloc是枢轴位置 
		Qsort(L, low, pivotloc - 1);
		Qsort(L, pivotloc + 1, high);
	}
}

如果L[0]上面有数字(不闲置),稍微改动一下就可以了

int Patition(int L[], int low, int high)
{
    int temp = L[low];
    while(low < high)
    {
        int pivotkey = L[low];
        while(low < high && L[high] >= pivotkey)high--;
            L[low] = L[high];
        while(low < high && L[low] <= pivotkey)low++;
            L[high] = L[low];
    }
    L[low] = temp;
    return low;
}

void Qsort(int L[], int low, int high)
{//调用前置low = 0, high = L.length - 1
    if(low < high)
    {
        int pivotloc = Patition(L, low, high);
        Qsort(L, low, pivotloc - 1);
        Qsort(L, pivotloc + 1, high);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值