【算法】學習筆記(4):分治思想 歸并排序

分治思想,分治策略,自古有之,與人類生活息息相關,其本質是將大問題拆解為小問題,小問題轉換為已知解的問題,進而求解。

軍隊管理,國家分級治理……

在這里插入圖片描述

大規模數據排序,例如10000000000萬個數,規模大的時候,分治思想就很重要了。

基本思想

分!如果問題還大,就再分!直到其變成容易求解的基本問題,這個過程其實與遞歸的類似的。

在這里插入圖片描述
總而言之,遞歸思想與分治策略,有著密不可分的聯系。

對于分解之后的基本問題,我們就可以使用一些基本的策略求解,因為容易,比如枚舉。

在這里插入圖片描述

核心策略

  1. 分:大問題–> 小問題 --> 基本問題
  2. 治:解決基本問題
  3. 合:將基本問題的解合并,得到原問題的解
    在這里插入圖片描述在這里插入圖片描述
    抽象的理論內容,很重要,我們把握其核心思想和本質,但是,想要理解抽象,我們更應該解決實際問題,在實際問題中理解抽象概念,達到融會貫通。

基本框架程序

在這里插入圖片描述
在這里插入圖片描述

  1. 理解問題
  2. 分解問題,找到自己認識的部分;或者,從最簡單情況出發,遞推地分析一下
  3. 獲得簡單問題的求解辦法
  4. 將大問題遞歸地分解為簡單問題去處理
  5. 將每個小問題的解合并

如此抽象,說了也白說,直接上例子。

歸并排序

最難點:【合】的策略,合無定法!

在這里插入圖片描述
分治策略與遞歸的對應關系

分:進行遞歸操作
治:遞歸終止條件和處理辦法
合:遞歸處理辦法

對于歸并排序

  1. 分:將數組不斷進行二分,直到其剩余1個元素
  2. 治:對于1個元素,一定是有序的,就可以將其作為基本問題的解返回
  3. 合:對于基本問題的解,需要讓其合并后有序,因此合并需要專門的一些策略,針對歸并排序特點進行設計。

合是最難的,因為合無定法,每種問題的每種解法,可能都不一樣。

看代碼:

#include <ctime>
#include <iostream>
using namespace std;// 給你一個規模很小的數組,并且告訴你分兩半,每一半都是有序的,讓你給合起來依然有序
// 合
void merge(int data[], int buffer[], int min, int mid, int max) {int first_mid_pointer = min;		// data[min, mid]int second_mid_pointer = mid + 1;	// data[mid+1, max]int buffer_pointer = min;			// buffer[min, max]while (first_mid_pointer <= mid && second_mid_pointer <= max) {if (data[first_mid_pointer] <= data[second_mid_pointer]) {buffer[buffer_pointer] = data[first_mid_pointer];buffer_pointer++;first_mid_pointer++;}else{buffer[buffer_pointer++] = data[second_mid_pointer++];}}// 傳遞剩余部分if (first_mid_pointer <= mid) {while (first_mid_pointer <= mid && buffer_pointer <= max) {buffer[buffer_pointer++] = data[first_mid_pointer++];}} else {while (second_mid_pointer <= max && buffer_pointer <= max) {buffer[buffer_pointer++] = data[second_mid_pointer++];}}}// 歸并排序
void merge_sort(int data[], int buffer[], int min, int max) {// 治if (min >= max)return;if (min < max){// 分int mid = (max + min) / 2;	// + ;not -merge_sort(data, buffer, min, mid);merge_sort(data, buffer, mid + 1, max);// 合(“治”之后才會執行)merge(data, buffer, min, mid, max);// buffer result --> datafor (int i = min; i <= max; i++) {	// 注意起點和終點,注意“=”data[i] = buffer[i];}}
}int main()
{clock_t start, end;for (int n = 64; ; n *= 2) {// initializationint *a = new int[n];for (int i = 0; i < n; i++) {a[i] = rand() % 10000 + 1;}// merge sortstart = clock();int length = n; //sizeof(a) / sizeof(a[0]);int *buffer = new int[length];merge_sort(a, buffer, 0, length - 1);end = clock();cout << "N = " << n << "   time = " << end - start << endl;if ((end - start)*2 > 180000)	// predict: more than 3 minutes,stop!break;}return 0;}

類似版本的代碼

#include <iostream>
using namespace std;// combine function
// data sequence: min to max
void combine(int data[], int buffer[], int min, int mid, int max) {// NOTE: max = length of array - 1int before_mid_pointer = min;		// data[min,mid]int after_mid_pointer = mid + 1;	// data[mid+1,max]int buffer_pointer = min;			// buffer[min,max]while (before_mid_pointer <= mid && after_mid_pointer <= max){if (data[before_mid_pointer] <= data[after_mid_pointer])buffer[buffer_pointer++] = data[before_mid_pointer++];elsebuffer[buffer_pointer++] = data[after_mid_pointer++];}// process the rest of data that is not be compared// add them to buffer directlywhile (before_mid_pointer <= mid && buffer_pointer <= max){buffer[buffer_pointer++] = data[before_mid_pointer++];}while (after_mid_pointer <= max && buffer_pointer <= max){buffer[buffer_pointer++] = data[after_mid_pointer++];}// add buffer to datafor (int i = min; i <= max; i++) {data[i] = buffer[i];}}// 自始至終,我們都是使用一個data和一個buffer,通過指針值“虛擬地”分割和排序。
// merge sort
void merge_sort(int data[], int buffer[], int min, int max) {if (max > min) {// divideint mid = (max + min) / 2;merge_sort(data, buffer, min, mid);merge_sort(data, buffer, mid + 1, max);// combine: sort two sorted arrays using specified methodcombine(data, buffer, min, mid, max);} else {// conquer: only 1 elementreturn;}
}int main() {int data[8] = { 1,3,5,0,100,4,33,7 };int buffer[8] = { 0 };merge_sort(data, buffer, 0, 7);for (int i = 0; i < 8; i++) {cout << buffer[i] << "  ";}return 0;
}

小結

分治思想,用一個成語就是庖丁解牛,完整的牛我們搞不懂,就將其合理地拆解,分成小部分,然后就可以搞定了。

還需要大量實例去體會分、治、合的思想策略。

我們知道了分治策略與遞歸思想的結合。

治理的是基本問題,也就是遞歸的結束條件和結束時候的處理辦法。

而分則是遞歸調用過程,它指明了我們應該如何調用遞歸函數去分割問題,使其更簡化。

最后,,則是在某個遞歸函數返回之后的處理辦法,它也在遞歸處理過程內,只有遞歸返回后,才會執行,用于合并返回的基本問題的解,從而得到最終的復雜問題的解。

對于歸并排序,我們有一個比較神奇的點,那就是,自始至終,data和buffer都使用的是一個,而所謂的分割,都是通過虛擬的指針來實現的,我們并沒有真地將其分割!

算法學習策略

  1. 原理與思想本質
  2. 實例與圖解
  3. 實際問題分析
    1. 抽象
    2. 實現

需要這幾個過程,才能真正體會算法思想的精髓,通過大量實例和圖解,能夠更好地理解算法,理解思想本質。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384636.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【算法】學習筆記(5):快速排序

注意一個C的坑 sizeof()這個函數靜態數組可以求長度&#xff0c;動態new出來的數組不行&#xff0c;因為針對的是指針……&#xff0c;不過既然的動態數組了&#xff0c;其長度本身必然是一個變量了&#xff0c;你沒有必要這么求長度。 下面看快速排序的代碼。 #include <…

【計算機系統設計】實踐筆記(6)改進數據通路:lw和sw指令

不想多說了……前面的鋪墊足夠了&#xff0c;剩下的自己做做應該也會了&#xff0c;如果遇到問題&#xff0c;就搜一下自己查閱就好。 這篇水過&#xff0c;沒有太多技術點。 唯一注意的是&#xff0c;引入的RAM和ROM的clk觸發問題&#xff0c;可能引起時序問題&#xff0c;等…

html css 核心設計理念

分開看&#xff01; 從不同視角&#xff0c;獨立地去看某一部分內容&#xff0c;使用聚焦視角&#xff0c;進行獨立操作和批量操作。

html css 學習筆記(1)背景相關

背景顏色 圖片 插入圖片img背景圖片 背景圖片 3. logo 4. 大圖 5. 裝飾性小圖 便于控制位置&#xff01; 插入后會執行自動平鋪&#xff0c;這與插入圖片是不同的&#xff01; div{width: 600px;height: 300px;background-image: url(img/登錄用戶頭像.png); }小結 盒子的第…

html css a標簽的應用

作為普通鏈接轉換為行內塊元素 轉換為行內塊元素之后&#xff0c;就可以給其各種塊行為&#xff0c;加背景&#xff0c;加背景圖片&#xff0c;設置寬高&#xff0c;內外邊距…… 塊行為可以的&#xff0c;它都行&#xff0c;唯一的區別&#xff0c;它這個盒子是個鏈接&#…

GitHub回滾

不要直接退回到很久前的歷史版本&#xff0c;這很可能引起文件沖突&#xff0c;可以一步步回滾&#xff0c;先回滾最近的&#xff0c;從近到遠一步步滾到目標。

2020-12-15 CPU設計復盤

SOC修改 將之前完成的31條指令單周期CPU進行了重構&#xff0c;將其分開&#xff0c;實現了內外有別&#xff0c;將CPU、指令ROM和數據RAM。 這樣&#xff0c;以后為其增加接口外設&#xff0c;總線控制&#xff0c;才更加清晰&#xff0c;這是進一步封裝和抽象。 MARS大坑 …

Tomcat 學習筆記(0)

JavaWeb 用Java寫的程序&#xff0c;可以在瀏覽器運行。 Request & Responce Web資源 Web服務器 我們在自己的主機啟動Tomcat服務器&#xff0c;然后運行它&#xff0c;就能夠通過主機訪問這個服務器&#xff0c;這個服務器能夠運行我們的程序。 部署Web工程 法1 將web…

計算機系統 學習筆記(0)南京大學(一)第一周

課程&#xff1a;計算機系統基礎 核心理念&#xff1a;人類世界與計算機世界的異同 人類世界 直觀感受數學 計算機世界 與數學不同&#xff0c;存儲首先&#xff0c;各層次與現實世界不同 我們關注點是差異點&#xff01; 一樣的你就不用關心了&#xff0c;關心差異&#…

x86架構下 CF與OF標志位 帶符號和無符號運算 詳解

針對能夠影響OF和CF標志位的指令&#xff0c;一般來說是涉及到數據運算的指令&#xff0c;這里使用add舉例&#xff0c;即不區分有無符號的加法指令&#xff0c;參與運算的數據&#xff0c;從二進制層級去考慮。 CF標志位 對于CF&#xff0c;它是carry flag&#xff0c;進位標…

tmux學習筆記

參考學習鏈接 我們需要理解幾個重要的概念 session 回話window 窗口pane 窗格 window 我們打開的一個terminal就是一個window. 而打開的這個window&#xff0c;也就是打開了一個session&#xff0c;打開window&#xff0c;session開始&#xff1b;關閉window&#xff0c;se…

安裝win10和Linux雙系統的個人經驗

使用easy uefi誤刪除win10引導文件 這個時候&#xff0c;網上教程有各種方式&#xff0c;我直接使用了一種最簡單的&#xff0c;這個方法網上都沒有提到過。 注意&#xff1a;發現引導文件刪了&#xff0c;千萬不要關機&#xff0c;否則再想開機恐怕只能重裝系統了。 我們直…

Linux的ext4文件系統學習筆記

補充&#xff1a;設備獨立性 Linux中&#xff0c;設備驅動以文件形式表示&#xff0c;用戶操作邏輯設備就是操作文件&#xff0c;而不是具體的物理設備&#xff0c;也就是說&#xff0c;用戶操作的是功能&#xff0c;是黑箱&#xff0c;而不是真正的實體。 APP操作的都是邏輯…

html基礎元素案例筆記(1)

這是代碼 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>CSS FlexBox test</title><link rel"stylesheet" type"text/css" href"./css/index.css"></head><body>…

C語言中的struct和union區別

參考&#xff1a;Difference between Structure and Union in C 二者區別 struct 這里不做詳細說明&#xff0c;因為參考鏈接中都寫明了。只做一些重點強調。 struct中聲明的變量&#xff0c;在分配空間的時候&#xff0c;struct結構空間大小&#xff0c;大于等于其內部所有…

C語言多文件編譯鏈接為1個可執行文件的簡單原理

參考1&#xff1a;C header files and compilation/linking 參考2&#xff1a;計算機系統基礎&#xff08;一&#xff09;袁春風 &#xff08;符號鏈接部分&#xff09; 我們現在有一個簡單的工程&#xff0c;有這么幾個文件 1.t1.h extern int x;void tt();t1.c #include &…

Java讀寫二維數組到文件

1. 創建文件 使用了File類中的createrNewFile方法。 public static boolean createFile(String filename){try{File file new File(filename);file.createNewFile();return true;} catch (IOException e) {e.printStackTrace();return false;}}查閱文檔可知&#xff0c;若文件…

如何掌握java API的方法

如何掌握方法的使用&#xff1f; 查文檔文檔不一定看得懂&#xff0c;親自試一試就知道了&#xff01; 這倆方法沒啥好說的&#xff0c;自己體會即可&#xff01; 注意&#xff01;先看原版英文文檔&#xff0c;然后自己試一試&#xff0c;就能更加理解了&#xff0c;然后&a…

Leetcode1512. 好數對的數目 抽出本質原型 利用范圍條件

解法1&#xff1a;暴力枚舉 class Solution {public int numIdenticalPairs(int[] nums) {int count 0;for(int i 0;i < nums.length; i){for(int j i 1; j < nums.length; j){if(nums[i] nums[j])count;}}return count;} }沒啥可說的&#xff0c;就是小學數學問題…

leetcode面試題 10.01. 合并排序的數組

直接排序 直接使用Java已有的方法進行排序&#xff0c;這一招…大意了&#xff01; 這題簡單&#xff0c;就是個基本的排序&#xff0c;后面難題&#xff0c;可能這只是一小步&#xff0c;內個時候直接用排序算法比較合適&#xff0c;這個不合適。。 class Solution {public…