数据结构&算法学习笔记: 快速排序

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

快速排序的思想

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

如何进行划分

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

步骤

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

时间复杂度

最坏: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);
    }
}

你可能感兴趣的:(排序,算法学习笔记)