筆記:C++五一學習-分治

今天是五一,晚上學C++分治算法

1、二分查找

二分查找跨度大,速度快,枚舉的跨度爲1,所以慢
二分是折半的,速度logn,非常快,基礎代碼如下
參數aTarget是目標數,aData是數列,n是數組長度
如果按照枚舉的方法,是這樣的:

bool Search(int aTarget, int aData[], int n)
{
	for (int i = 0; i < n; i++)
		if (aData[i] == aTarget)
			return true;
	return false;
}

這樣對於小範圍的數據是可以處理的
但是:如果要遍歷兩億個數呢?而且碰巧要找到的數是兩億減一的數呢?😱


於是二分查找出現了!😇
數組方法如下:

bool binarySearch(int aTarget, int aData[], int n)
{
	int left = 0, right = n - 1;
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (aData[mid] == aTarget)
			return true;
		else if (aData[mid] < aTarget)
			left = mid + 1;
		else
			right = mid - 1;
	}
	return false;
}

換成動態數組更簡單了

bool binarySearch(int aTarget, vector<int> aData)
{
	int left = 0, right = aData.size();
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (aData[mid] == aTarget)
			return true;
		else if (aData[mid] < aTarget)
			left = mid + 1;
		else
			right = mid - 1;
	}
	return false;
}

最簡單的還是algorithm庫中的函數,直接給圖
在這裏插入圖片描述

1、1二分查找練習題-砍樹

在這裏插入圖片描述
這個題目用枚舉顯然不行,於是二分查找又偉大的出現了!
其實很簡單

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
int main()
{
	vector<int>trees;
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		int tmp;
		cin >> tmp;
		trees.push_back(tmp);
	}
	sort(trees.begin(), trees.end());
	//inend
	printf("trees[trees.size() - 1] = %d\n", trees[trees.size() - 1]);
	int left = 1, right = trees[trees.size() - 1];
	int ans;
	printf("----\n");
	while (left <= right)
	{
		int all = 0;
		int mid = (left + right) / 2;
		printf("left = %d, right = %d, mid = %d\n", left, right, mid);
		for (int i = 0; i < trees.size(); i++)
			if (trees[i] - mid < 0)
				all += 0;
			else
				all += trees[i] - mid;
		cout << "all:" << all << endl;
		if (all < m)
			left = mid + 1;
		else
			right = mid - 1;
		ans = all;
	}
	cout << ans << endl;
	return 0;
}

2、快速排序

這是一個經典的分治,我有一個動圖來演示!
它的基本原理是基準數
在這裏插入圖片描述
給一個快速排序的地址:https://www.jianshu.com/p/497b8ee8b517
整個排序算法專欄:https://www.jianshu.com/c/0b8a16f39eab

歸併排序也是基於分治的思想,不過歸併流程是將子集合合併成爲有序的集合,遞歸執行來完成整個集合的排序。快速排序的分治流程是根據選定元素,將集合分隔爲兩個子集合,一個子集合中所有元素不大於選定元素值,另一個子集合中所有元素不小於選定元素值,則用於拆分集合的選定元素即爲已排序元素。即每次拆分都會形成一個已排序元素,所以 個元素的序列,拆分的次數級別爲O(N)。將拆分過程類比爲二叉樹形式,考慮普通二叉樹和斜樹的情況,則二叉樹高度級別爲O(log2N)~O(N)。


作者:zhipingChen
鏈接:https://www.jianshu.com/p/497b8ee8b517
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。


實現!
迭代法

typedef struct _Range {
    int start, end;
} Range;
Range new_Range(int s, int e) {
    Range r;
    r.start = s;
    r.end = e;
    return r;
}
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort(int arr[], const int len) {
    if (len <= 0)
        return; // 避免len等於負值時引發段錯誤(Segment Fault)
    // r[]模擬列表,p為數量,r[p++]為push,r[--p]為pop且取得元素
    Range r[len];
    int p = 0;
    r[p++] = new_Range(0, len - 1);
    while (p) {
        Range range = r[--p];
        if (range.start >= range.end)
            continue;
        int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點
        int left = range.start, right = range.end;
        do
        {
            while (arr[left] < mid) ++left;   // 檢測基準點左側是否符合要求
            while (arr[right] > mid) --right; //檢測基準點右側是否符合要求
 
            if (left <= right)
            {
                swap(&arr[left],&arr[right]);
                left++;right--;               // 移動指針以繼續
            }
        } while (left <= right);
 
        if (range.start < right) r[p++] = new_Range(range.start, right);
        if (range.end > left) r[p++] = new_Range(left, range.end);
    }
}

遞歸法

void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort_recursive(int arr[], int start, int end) {
    if (start >= end)
        return;
    int mid = arr[end];
    int left = start, right = end - 1;
    while (left < right) {
        while (arr[left] < mid && left < right)
            left++;
        while (arr[right] >= mid && left < right)
            right--;
        swap(&arr[left], &arr[right]);
    }
    if (arr[left] >= arr[end])
        swap(&arr[left], &arr[end]);
    else
        left++;
    if (left)
        quick_sort_recursive(arr, start, left - 1);
    quick_sort_recursive(arr, left + 1, end);
}
void quick_sort(int arr[], int len) {
    quick_sort_recursive(arr, 0, len - 1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章