算法分析——分治策略

1 分治策略概念

分治法是講一個複雜的問題分成兩個或者更多的相同或者相似的問題,這些子問題相互獨立或者形式相同,再把子問題分解成更小的子問題,一直這樣循環下去,直到最後子問題可以簡單的直接求解,原問題的解即子問題解得合併。

例1.1

給定一個順序表,編寫一個求出其最大值與最小值的分治算法。

分析:假設我們的數據按順序的存放在一個整型數組中,如果數組大小爲1,那麼就可以直接給出結果,如果大小爲2,那麼比較一次就可以給出結果,如果求解問題數組長度大於2,我們就把問題規模縮小,直到縮小到問題可以解決爲止,所以分治策略算法如下:

#include "pch.h"
#include <iostream>
using namespace std;
//s代表當前分治段的起始下標,e代表結束下標,meter代表數組地址,max,min分別代表存放最大值最小值的地址
void partionGet(int s, int e, int *meter, int *max, int *min)
{
	if (e - s <= 1)
	{
		if (meter[s] > meter[e])
		{
			if (meter[s] > *max)
				*max = meter[s];
			if (meter[e] < *min)
				*min = meter[e];
		}
		else
		{
			if (meter[e] > *max)
				*max = meter[e];
			if (meter[s] < *min)
				*min = meter[s];
		}
		return;
	}
	int i = s+(e-s) / 2;
	partionGet(s, i, meter, max, min);//在這裏使用了二分法
	partionGet(i+1, e, meter, max, min);

}
int main()
{
	int max=0, min=0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	partionGet(0, 9, arr, &max, &min);
	cout << max << " " << min << endl;
	return 0;
}

排序問題

例1.2

歸併排序,簡單來說,歸併排序就是利用了分治策略,樓主專門寫過一篇關於歸併排序遞歸算法與非遞歸算法的實現,在這裏就不在重複寫了,請點擊下連接。

https://mp.csdn.net/postedit/83180119

例1.3

快速排序是一種基於分治策略排序的一種算法。其基本思想是對於給定的待排序序列a[p:r],按照以下步驟進行:

(1)分解,一a[p]作爲基準將數組a[p:r]劃分成三段a[p:q-1],a[q]和a[q+1:r],使a[p:q-1]中任何一個元素都小於a[q],a[q+1:r]中任何一個元素都大於a[q].下標q在劃分過程中確定。

(2)遞歸求解,通過遞歸調用快速排序算法對a[p:q-1]和a[q+1:r]進行排序。

(3)合併,對於a[p:q-1]和a[q+1:r]的排序是就地進行的,所以在a[p:q-1]和a[q+1:r]都已經排好序後,,不需要進行任何計算,a[p:r]已經排好序。

基於這個思想,可實現快速排序算法:

void quickSort(int arr[], int left, int right)
{//對arr數組進行快拍,按照非遞減有序排列
	if (left < right)//如果元素序列長度小於一不處理
	{
		int pivotpos = Partition(arr, left, right, right - left + 1);//一趟劃分
		quickSort(arr, left, pivotpos);//處理左側序列
		quickSort(arr, pivotpos + 1, right);//處理右側序列
	}

對於含有n個元素的數組arr[0:n],進行快速排序只要調用quickSort(arr,0,n)即可。

算法中Partition是以一個確定的基準元素arr[p]對子數組arr[p:r]進行劃分。

int Partition(int arr[], int low, int high, int num)
{
	int i = low, j = high, pivot = arr[low];//基準元素
	while (i < j)
	{
		while (i < j&&arr[j] >= pivot)//反向掃描,找第一個比基準小的元素,移到左邊
			j--;
		if (i < j)
		{
			arr[i] = arr[j];
			i++;
		}
		while (i < j&&arr[i] < pivot)//找比基準大的元素,移到右邊
			i++;
		if (i < j)
		{
			arr[j] = arr[i];
			j--;
		}
	}
	arr[i] = pivot;//將基準元素就位
	return i;
}

未完。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章