递归和分治及其应用(分治、快速排序)

分治法

  1. 定义:使用递归的技巧,可以将一个问题拆分成两个或更多较小的局部问题,利用递归函数求出每个局部问题的劫,然后再将结果整合,最终解决问题,这种编程手法称为分治法。

  2. 分治法的核心是将问题分割、拆解为同类的小问题(神似套娃),再进行整合。但是在设计时必须要留有终点。

高等排序

当数据庞大或在一些体积庞大的数组面前,冒泡排序(复杂度高达o(n^2))的初等排序就失去了实用价值,通常在竞赛中会出现超时。由此就会用到高等排序。其中,包括归并排序、快速排序和计数排序(桶排序)。

归并排序

算法核心

1.将给定的包含n个元素的局部数组“分割”成两个局部数组,每个数组各包含n/2个元素。

2.对两个局部数组分别执行mergesort排序。

3.通过merge将两个以排序完毕的局部数组整合为一个数组。

实例:ALDS1_5_B:Merge Sort


//输入一串数字,排序后输出排序完毕的数字,并输出比较运算的次数。

#include<stdio.h>
#include<iostream>
using namespace std;

const int MAX = 500005;
const int SENRINRL = 200000000;

int cnt;
int l[MAX/2+2], r[MAX / 2 + 2];

void merge(int s[], int n, int left, int mid, int right)
{
    int n1 = mid - left;
    int n2 = right - mid;
    for(int i = 0; i < n1; i++)     l[i] = s[left+i];
    for(int i = 0; i < n2; i++)     r[i] = s[mid+i];
    l[n1] = r[n2] = SENRINRL;
    int i = 0, j = 0;
    for(int k = left; k < right; k++)
    {
        cnt++;
        if(l[i] <= r[j])
            s[k] = l[i++];
        else
            s[k] = r[j++];
        
    }
}

void mergeSort(int s[], int n, int left, int right)
{
    if(left+1 < right)
    {
        int mid = (right + left) / 2;
        mergeSort(s, n, left, mid);
        mergeSort(s, n, mid, right);
        merge(s, n, left, mid, right);
    }    
}


int main(void)
{
    int n;
    int s[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> s[i];
    }

    mergeSort(s, n, 0, n);

    for(int i = 0; i < n; i++)
    {
        if(i != 0)
            cout << " ";
        cout << s[i];
    }
    cout << endl;
    cout << cnt << endl;

    return 0;
}

快速排序

快速排序是基于分治法的算法。

算法核心

1.通过分割直接将对象局部数组分割为前后两个局部数组。

2.对前半部分的局部数组执行quickSort.

3.对后半部分的局部数组执行quickSort.

注意:

1.快速排序在分割的过程中会交换不相邻的元素,因此属于不稳定的排序算法。而且,与归并排序不同,快排不必额外占用内存。

2.在C++STL 标准库中有sort函数,基于快速排序,但与快排相同,是不稳定的排序算法。若需要稳定的排序算法,可以蚕蛹以归并排序为基础的stable_sort。但就日常竞赛做题而言,多用sort.

3.sort详情:

(1)sort函数包含在#include<algorithm>头文件中;

(2)sort有三个参数:sort(start, end, 排序方法)

       第一个参数是要排序的数组的起始地址;第二个参数是要排序数组的最后一位要排序的地址;第三个参数是排序方法,默认为由小到大。

快排实例(C语言实现):

#include<stdio.h>

void Quicksort(int a[], int s, int e)
{
	int temp;
	if(s >= e)
		return;
	int k = a[s];
	int i = s, j = e;
	while(i != j){
		while(j > i && a[j] >= k)
			j--;
		temp = a[i];
		a[i] = a[j]; 
		a[j] = temp;
		while(i < j && a[i] <= k)
			i++;
		temp = a[i];
		a[i] = a[j]; 
		a[j] = temp; 
	}
	Quicksort(a, s, i-1);
	Quicksort(a, i+1, e);
}

int a[] = {1, 51, 4, 87, 55, 66, 12, 35};
int main(void)
{
	int i;
	int size = sizeof(a) / sizeof(int);
	Quicksort(a, 0, size-1);
	for( i = 0; i < size; i++){
		printf("%d  ", a[i]);
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值