“挖坑填坑”理解快速排序

来源:互联网 发布:弈乐麻将 游戏网络 编辑:程序博客网 时间:2024/06/06 02:12

    快速排序的基本思路:找一个基准元素,对数组进行调整,调整的标准是,这个基准元素的左边存放的都是比这个元素小的,右边都是比这个元素大的。然后分而治之,对左右两边的子数组利用同样的规则调整,调整到每一个子数组中都只有一个元素时结束。

    基本思想很简单,主要是理解如何在确定基准元素之后,对数组(子数组)进行调整,下面举个例子,用“挖坑填坑”(拆了东墙补西墙)的比喻来理解一次调整的过程。

一个无序数组:[4, 3, 7, 5, 10, 9, 1, 6, 8, 2]

1.      随便先挖个坑,就在第一个元素(基准元素)挖坑,挖出来的“萝卜”(第一个元素4)在“篮子”(临时变量)里备用。挖完之后的数组是这样:[ , 3, 7, 5, 10, 9, 1, 6, 8,2]

2.      挖右坑填左坑:从右边开始,找个比“萝卜”(元素4)小的元素,挖出来,填到前一个坑里面。填坑之后:[ 2, 3, 7, 5, 10, 9, 1, 6, 8,]

3.      挖左坑填右坑:从左边开始,找个比“萝卜”(元素4)大的元素,挖出来,填到右边的坑里面。填坑之后:[ 2, 3,, 5, 10, 9, 1, 6, 8, 7]

4.      挖右坑填左坑:从右边开始,找个比“萝卜”(元素4)小的元素,挖出来,填到前一个坑里面填坑之后:[ 2, 3, 1, 5, 10, 9,, 6, 8, 7]

5.      挖左坑填右坑:从左边开始,找个比“萝卜”(元素4)大的元素,挖出来,填到右边的坑里面填坑之后:[ 2, 3, 1,, 10, 9, 5, 6, 8, 7]

6.      挖右坑填左坑:从右边开始,找个比“萝卜”(元素4)小的元素,挖出来,填到前一个坑里面,这一次找坑的过程中,找到了上一次挖的坑了,说明可以停了,用篮子里的的萝卜,把这个坑填了就行了,并且返回这个坑的位置,作为分而治之的中轴线。填坑之后:[ 2, 3, 1,4, 10, 9, 5, 6, 8, 7]

上面的步骤中,第2,4, 6其实都是一样的操作,3和5的操作也是一样的。

代码如下:

int _qucikly_sort(int arr[], int low, int high) {  int pivot = arr[low]; //挖第一个坑,把“萝卜”放进篮子  while(low<high) { //开始循环挖坑填坑    //如果low等于high,说明找坑的过程中,找到了上一次挖的坑,因此可以停止了    while(low<high && arr[high]>=pivot) //从右边往左边找填坑的元素(比pivot小的元素)。 2,4,6的过程      --high;    arr[low] = arr[high]; //将找到之后,挖出来,填到左边的坑里    while(low<high && arr[low]<=pivot) //从左边往右边找填坑的(比pivot大的元素)。3,5的过程      ++low;arr[high] = arr[low];//找到之后,填到右边的坑里  }  arr[low] = pivot; //篮子里的“萝卜”填到坑里  return low;//返回这个坑的位置,作为分而治之的中轴}


分而治之的代码:

void quickly_sort(int arr[], int low, int high) {  if (low < high) {    int pivot = _qucikly_sort(arr, low, high);      quickly_sort(arr, low, pivot-1);    quickly_sort(arr, pivot + 1, high);  }}


测试代码:

#include <stdio.h>#include <stdlib.h>void display(int arr[], int len) {  for(int i = 0; i < len;i++)    printf("%d ", arr[i]);  printf("\n");}int main() {  int arr[] = {4, 3, 7, 5, 10, 9, 1, 6, 8, 2};  quickly_sort(arr, 0, sizeof(arr)/sizeof(int) - 1);
  display(arr, sizeof(arr)/sizeof(int));  return 0;}








原创粉丝点击