c++两个vector合并_数据结构——算法初步(4)——合并排序算法
從之前的學習可以看到,對大型vectory要求的排序,選擇排序算法顯然不符合要求,因為運行時間與輸入問題規模大小的平方成比例增加,對于以線性順序處理向量的元素的大多數排序算法也是如此。 所以要采用不同的方法來開發更好的排序算法。我們可以試著反過來思考。
強大的分治法(divide-and-conquer)
分治法的具體詳見 C++抽象編程——遞歸簡介(1)——遞歸范式 我們先來看看排序算法的性能為什么在問題規模增大后變得如此糟糕?我們之前分析過二次復雜度(即O(N^2)類)的基本特征是,隨著問題的大小增加,運行時間增加了問題規模的兩倍(比如問題規模增加2倍,那么運行時間要增加4倍)。 然而,反過來我們可以這樣想。 如果將二次問題的大小除以2,則可以將運行時間減少相同的四倍。 也就是說我們可以將vector除以一半,然后應用遞歸的方法繼續將問題的規模拆分,就可以成倍的減少所需的排序時間。
舉個例子,假設你有一個很大的vector需要排序。如果將vector分成兩半,然后使用選擇排序算法對這些片段進行排序,會發生什么? 因為選擇排序是的復雜度是二次的,每個較小的vector需要原始時間的四分之一(問題規模減少了2倍,時間就提高4倍)。 當然,你需要對這兩半分別進行排序,但是排序兩個較小vector所需的總時間仍然是排序原始vector所需的時間的一半。如果分開一個vector的兩半可以簡化整個vector排序的問題,我們將能夠大大減少排序需要的總時間。更重要的是,一旦發現如何在一個地方提高性能,就可以使用相同的算法遞歸地對每一個進行排序。 為了確定分治法是否適用于這個排序問題,我們需要確定一個問題,即將vector分為兩個較小的vector,然后對每個vector進行排序是否有助于解決一般問題(也就是拿一個實例來分析一下)。假設你從一個包含以下八個元素的vector開始排序:
如果將8個元素的vector劃分為長度為4的兩個vector,然后對每個較小的vector進行排序,就會得到下圖:
現在我們需要從這些較小的vector中取出值,并將它們以正確的順序放回到原始vector中。
合并兩個vector
從較小的排序vector重組成完整的vector比排序本身要簡單得多。這個過程我們稱為合并(merging)。即完整排序中的第一個元素必須是v1中的第一個元素或v2中的第一個元素,以較小者為準。回到這個例子當中, 1. 我們新組成的的vector中的第一個元素是第二個vector(v2)中的第一個元素。然后將該元素添加到空的向量vec,此時我們把v2的19叉掉,表示已經取出,我們下圖的結果
2. 再來一次,下一個元素只能是兩個較小向量之一中的第一個未取出的元素。比較v1中的25與v2中的30,并選擇前者:
3. 重復此過程,從v1或v2中選擇較小的值,直到重構整個vector
合并排序算法
合并操作與遞歸分解相結合,產生了一種稱為合并排序的新的排序算法,可以直接實現。 算法的基本思想可以概括如下:
1. 檢查vector是否為空或只有一個元素。如果是這樣,它肯定已經被排序。此條件用于定義遞歸的simple case。
2. 將vector分成兩個較小的vector,每個vector的大小是前者的一半(意味著,不是值分成兩個vector,而是每個分開的vector還可以繼續分,重復這個過程)
3. 遞歸地對每個較小的vector進行排序。
4. 清除原始的vector,使其再次為空。(用來儲存新的排序好的數字)
5. 將兩個排序好的vector合并回原來的vector。
合并排序的C++代碼
合并排序思路簡單,但是實現起來并不那么容易,下面是本人寫的C++代碼,在VS2015中編譯通過:
/*運行效果如圖:
合并排序算法的代碼可以整齊地分為兩個函數:排序和合并。 排序代碼直接來自算法的步驟。在檢查特殊情況后,算法將原始vector分為兩個較小的v1和v2。一旦sort代碼將所有元素復制到v1或v2中,v1,V2就已經被創建,其余的函數會遞歸地排序這些vector,最后清除原始vector,然后調用merge來重新組合vector,從而實現合并排序。 實際上大部分的工作是通過合并函數完成的,該函數采用目標vec,以及較小的向量v1和v2。指標p1和p2標記跟蹤每一個vector的下標。 在循環的每個循環中,該函數從v1或v2選擇一個元素取較小者,并將該值添加到vec的末尾。一旦兩個較小的vector中的任何一個的元素被取盡,該函數可以簡單地從另一個vector中直接復制元素而再比較它們。實際上,因為這些向vector中的其中一個已經在第一個while循環退出時已經耗盡,所以該函數可以將vector的其余部分復制到vec。 其中一個vector為空,相應的while循環將完全不執行。
這里說一下,v1[p1++],其實我們都知道 i++返回的 i的值是自增1的。但是這個運算符返回的是自增前的值。也就是說比如 i = 2,執行
i++;之后,就是 i = 3,但是 (i++)這個整體的值就還是 2(可以寫個程序試試)。 所以說
v1[p1++]這句代碼等價于:
v1[p1]; p1 ++;下一篇的文章我們就去分析一下這個算法的復雜度
總結
以上是生活随笔為你收集整理的c++两个vector合并_数据结构——算法初步(4)——合并排序算法的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 民生信用卡专家门诊预约怎么办理
- 下一篇: python输入序列语句_Python基
