D&C思想-快速排序算法

只能解决一种问题的算法,用处必然是有限的.所以今天介绍一种解决问题的思路,一个可以让我们使用的工具.

Divide and Conquer 分而治之

先来说明一下D&C的工作原理:

(1) 找出简单的基线条件

(2) 确定如何缩小问题的规模,使其符合基线条件.


首先看一个例子

10 20 30

比如我们要把上面几个数字相加,你首先想到的是什么?
我开始的时候,想到的是循环,我想你们应该也有和我想得一样的吧.

那好,今天我们换个思路,用我们的D&C的思想来解决.

  • 上面的基线条件是什么?
  • 如何缩小它的规模,来符合我们的基线条件?

我们在计算一个整形数组的和的时候,最简单的情况是什么?

1.数组为空
2.数组只有一个元素

大多数情况下,我们要计算数组的和,那这个数组一般情况下是不会为空的.所以,我们的最理想的情况就是数组只有一个元素.基线条件已确定.

接下来,该如何将它分解到基线情况呢?

 1.把第一个元素拆出来: 10 + sum(20+30)
 2.把第二个元素拆出来: 10 + sum(20 + sum(30))

一层一层递进,就可以求出数组所有元素的和.
好,下面看一下python代码:

def sum(L):
	
	#递归的退出条件
	if l == []:
		return 0
	return l[0] + sum(l[1:])

D&C思想了解了后,最后我们再看一下快速排序

快速排序是一种常用的排序算法,比选择排序快的多.

对一个数组进行排序,那什么情况是基线呢?其实和数组求和一样.如果这个数组是空,或者数组的只有一个元素,那么排序就很简单了,就是它自己.

先对一个含有三个元素的数组排序
7 2 10

应用快速排序时,得先选择一个元素作为基准值(pivot),一般情况下,我们选择第一个元素作为基准值.

对于上面的数组,选择7作为基准值.

然后,向后遍历,遇到一个小于基准值的元素,放到基准值的左边.遇到一个大于基准值的元素,放到基准值的右边.这被称为分区(partitioning).

看一下现在的情况:

  • 一个由所有小于基准值的数字组成的字数组;
  • 基准值;
  • 一个由所有大于基准值的数组组成的字数组.

现在,对于这个只有三个元素的数组,已经排序完毕.

然后,看一下含有4个元素的数组

12 8 2 15

首先,12作为基准值,进行排序,第一轮完毕之后,是这个样子的:

8 2 12 15

现在,排列情况是:

<基准值 基准值 >基准值

大于基准值的部分,只有一个元素,不需要排序了.
小于基准值的部分,两个元素,同样,我们按照上面的方法,递归调用,进行排序.最后,得到了:

2 8 12 15

那,对于5个元素,6个元素,上千,上万的元素呢?同样啊,进行递归的调用,就可以排序了.

快速排序的python代码:

def quick_sort(arr):
	if len(arr) < 2:
		return arr
	else:
		pivot = arr[0]
		less = [i for i in arr[1:] if i < pivot]
		greater = [j for j in arr[1:] if j > pivot]
		return quick_sort(less) + [pivot] + quick_sort(greater)

print(quick_sort([2,8,12,15,32,4,56,12]))

输出结果:

[2, 4, 8, 12, 15, 32, 56]

快速排序的时间复杂度为O(nlogn)

注意:递归的退出条件一定要给出

最后,看一下快速排序的c语言实现

#include<stdio.h>

#define N 5

int arr[N] = {23,65,156,545,32};

void quick_sort(int arr[],int low,int high)
{
    //base value
    int pivot = arr[low];
    int i = low;
    int j = high;
    if(i > j)
       return;
    
    while(i < j)
    {
        while((i < j) && (arr[j] >= pivot))
            j--;
        if(i < j)
            arr[i] = arr[j];
        while((i < j) && (arr[i] <= pivot))
            i++;
        if(i < j)
            arr[j] = arr[i];
    }

    arr[i] = pivot;
    quick_sort(arr,low,i-1);
    quick_sort(arr,j+1,high);

}

void main()
{
    int i;
    quick_sort(arr,0,4);
    for(i = 0;i < 5;i++)
    {
        printf("%d \n",arr[i]);
    }
}

c语言的代码相对于python代码有点复杂.c代码中定义了两个指针,来指向正在遍历的元素,一个指向小于pivot的,一个指向大于pivot的.

猜你喜欢

转载自blog.csdn.net/weixin_37731316/article/details/89553011