c++排序算法

前言

我相信再看這篇文章的童鞋已經學完語言部分了吧。c++

學完語言後就應該學習算法,而最早應該學的算法就是排序算法

雖然排序函數(sort)能夠解決一切問題,可是這種(好)東西並非萬能的,在某些題目中,不只須要記錄排序後的答案,還須要記錄排序過程(例如排序的次數)數組

因此要想學到排序思想就只有一個辦法:函數

乖乖的寫幾遍代碼理解、背過學習


下面正式開啓文章內容優化


1、算法概述

十大常見算法基本上就能夠分紅兩類了spa

非線性時間比較類排序:經過比較來決定元素間的相對次序,稱爲非線性時間比較類排序。指針

線性時間非比較類排序:不經過比較來決定元素間的相對次序,以線性時間運行,稱爲線性時間非比較類排序。 code

下面這個圖就能夠清楚地分類:orm

思惟導圖好

下面就是各類排序算法的複雜度和是否穩定的表格。

Excel好

下面是註釋:

穩定:若是a本來在b前面,而a=b,排序以後a仍然在b的前面。(會交換)

不穩定:若是a本來在b的前面,而a=b,排序以後 a 可能會出如今 b 的後面。(不會交換)

時間複雜度:對排序數據的總的操做次數。反映當n變化時,操做次數呈現什麼規律。

空間複雜度:是指算法在計算機內執行時所需存儲空間的度量,它也是數據規模n的函數。

 在這裏我就不一一給你們講解各類算法了,我會挑5個給你們簡單講解。


 

2、算法講解

1.冒泡排序

我偷偷和你們說一下,本蒟蒻第一個學習的排序算法就是冒泡排序。

**********************************************************

  它重複地走訪過要排序的元素列,依次比較 兩個相鄰的元素,若是順序(如從大到小、首字母從Z到A)錯誤就把他們交換過來。走訪元素的工做是重複地進行 直到沒有相鄰元素須要交換,也就是說該元素列已經排序完成。
  這個算法的名字由來是由於越小的元素會經由交換慢慢「浮」到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端同樣,故名「冒泡排序」。
**********************************************************
使用方法:
比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。  
對每一對相鄰元素作一樣的工做,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。  
針對全部的元素重複以上的步驟,除了最後一個。
持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。
**********************************************************
冒泡排序最壞的時間複雜度是 O(n^2)
也就是說在數據很少的時候可使用。
這種方法是比較簡單好理解的!
上代碼!
//整數或浮點數皆可以使用
void Sort(a[], int len)
{
    int i, j,temp; for (i = 0; i < len - 1; i++) for (j = 0; j < len - 1 - i; j++) if (a[j] > a[j + 1]) { temp = a[j]; arr[j] = a[j + 1]; a[j + 1] = temp; } }

代碼已經給您找來了,其中的Sort函數即爲排序過程。


 

2.桶排序

爲何第二個就要學習桶排序嘞?

由於簡單

**********************************************************

桶排序或所謂的箱排序,是一個排序算法,工做的原理是將數組分到有限數量的桶子裏,每一個桶子再個別排序。

**********************************************************

使用方法:

把每個數字放在對應下標的「桶」中。

從頭輸出「桶」的下標。

**********************************************************

這是一種犧牲空間保空間的作法,數字有多大,就要開多大的數組。

而且不支持浮點數。

時間複雜度是O(n+c)

上代碼!

void Sort(int a[],int len)
{
    int x=0; for(int i=1;i<=len;i++) { b[a[i]]++; x=max(x,a[i]) } for(int i=0;i<=x;i++) { if(b[i]>=0) { while(b[i]!=0) { b[i]--; cout<<i; } } } }

代碼已經給您找來了,其中的Sort函數即爲排序過程。

 


 

3.歸併排序

**********************************************************

歸併排序是將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。

**********************************************************

使用方法:
申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列
設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置
比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間,並移動指針到下一位置
重複步驟3直到某一指針超出序列尾
將另外一序列剩下的全部元素直接複製到合併序列尾

**********************************************************

這是一種比較不錯的方法,這個方法也會分爲幾種:二路歸併和多路歸併。

這種方法也是利用了分治的方法,也就是分而治之。

你們能夠看一看下面的這個圖:(來源:百度百科)

上代碼!

void Merge(int* data,int a,int b,int length,int n)
{
     int right;   if(b+length-1 >= n-1) right=n-b;   else right=length;   int* temp=new int[length+right];   int i=0,j=0;   while(i<=length-1&&j<=right-1) {   if(data[a+i]<=data[b+j]) {   temp[i+j]=data[a+i];i++; }   else { temp[i+j]=data[b+j]; j++; }   }   if(j == right) {//a中還有元素,且全都比b中的大,a[i]還未使用   memcpy(temp + i + j, data + a + i, (length - i) * sizeof(int));   } else if(i == length) { memcpy(temp + i + j, data + b + j, (right - j)*sizeof(int)); }   memcpy(data+a, temp, (right + length) * sizeof(int));   delete [] temp; } void MergeSort(int* data, int n) {   int step = 1;   while(step<n) {  for(int i=0;i<=n-step-1;i+=2*step)   Merge(data,i,i+step,step,n); //將i和i+step這兩個有序序列進行合併 //序列長度爲step //當i之後的長度小於或者等於step時,退出  step*=2;//在按某一步長歸併序列以後,步長加倍   } } //因爲比較懶,因此這個也是百度百科的,我給稍加了調整。

懶癌發做……

 


 

4.選擇排序

這就是咱們常說的「打擂臺」的方法。

**********************************************************

選擇排序的工做原理是:第一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,而後再從剩餘的未排序元素中尋找到最小(大)元素,而後放到已排序的序列的末尾。以此類推,直到所有待排序的數據元素的個數爲零

**********************************************************

這個跟冒泡排序很像,但也有區別:

選擇排序與冒泡排序的區別:冒泡排序經過依次交換相鄰兩個順序不合法的元素位置,從而將當前最小(大)元素放到合適的位置;而選擇排序每遍歷一次都記住了當前最小(大)元素的位置,最後僅需一次交換操做便可將其放到合適的位置。

上代碼!

void Sort(int* h, size_t len)
{
    if(h==NULL) return; if(len<=1) return; int minindex,i,j; //i是次數,也即排好的個數;j是繼續排 for(i=0;i<len-1;++i) { minindex=i; for(j=i+1;j<len;++j) { if(h[j]<h[minindex]) minindex=j; } Swap(h[i],h[minindex]); } return; }

 代碼已經給您找來了,其中的Sort函數即爲排序過程。

5.插入排序

關於個人話……這個我真的沒什麼可說的了……直接介紹吧

**********************************************************

插入排序是一種簡單直觀且穩定的排序算法。若是有一個已經有序的數據序列,要求在這個已經排好的數據序列中插入一個數,但要求插入後此數據序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,算法適用於少許數據的排序,時間複雜度O(n^2)

**********************************************************

插入算法把要排序的數組分紅兩部分:第一部分包含了這個數組的全部元素,但將最後一個元素除外(讓數組多一個空間纔有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。

**********************************************************

若是過不理解的話看看這個圖片吧:(來源:百度百科)

百度百科好

上代碼!

void Sort(int* h, size_t len)
{
    if(h==NULL) return; if(len<=1) return; int i,j; //i是次數,也即排好的個數;j是繼續排 for(i=1;i<len;++i) for(j=i;j>0;--j) if(h[j]<h[j-1]) Swap(h[j],h[j-1]); else break; return; }

代碼已經給您找來了,其中的Sort函數即爲排序過程。


好了,到這裏這篇文章基本就結束了。
有可能你會問我爲何沒有介紹快速排序。
快速排序吧有不少種寫法,這裏就不寫了(洛谷模板我都沒過,我太弱了)。
可是思想我仍是要說一下的。
快速排序的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。
快速排序也就是冒泡排序的改進優化版。

6.其餘

在個人程序中,程序都沒有寫主函數,主函數的問題一個是輸入(若是過不會輸入請從新學習c++)

在一個就是尋找各類方法的標記點等等,這裏就不說了吧。


後記

這就是這篇文章的所有內容了,若是過有問題的話能夠經過側邊欄的QQ或者在評論區裏通知我,我會盡可能在第一時間查看。

還有就是……

客官,點個贊再走唄!

相關文章
相關標籤/搜索