排序演算法很容易被忽視,因為sort的存在,排序演算法不管是在面試還是競賽,都是很關鍵的演算法,所以今天整理一下。
重複地走訪過要排序的數列, 一次比較兩個元素, 如果他們的順序錯誤就把他們交換過來。 走訪數列的工作是重複地進行直到沒有再需要交換, 也就是說該數列已經排序完成。
void
bubble_sort
(int arry,
int left,
int right)}}
}
時間複雜度:o(n^2),
空間複雜度:o(n)
首先在未排序序列中找到最小( 大) 元素, 存放到排序序列的起始位置, 然後, 再從剩餘未排序元素中繼續尋找最小( 大) 元素, 然後放到已排序序列的末尾。 以此類推, 直到所有元素均排序完畢。
void
select_sort
(int arry,
int left,
int right)}if
(min != i)
}}
時間複雜度:o(n^2),
空間複雜度:o(n)
插入排序( insertion sort) 的演算法描述是一種簡單直觀的排序演算法。 它的工作原理是通過構建有序序列, 對於未排序資料, 在已排序序列中從後向前掃瞄, 找到相應位置並插入。 插入排序在實現上, 通常採用inplace排序( 即只需用到o(1)的額外空間的排序) , 因而在從後向前掃瞄過程中, 需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。
void
insert_sort
(int arry,
int left,
int right)
arry[j +1]
= tmp;
}}
時間複雜度:o(n^2),
空間複雜度:o(n)
快排是面試最喜歡問的演算法,基本思想其實就是二分和遞迴。
從序列中選取乙個作為關鍵字, 對序列排一次序, 使得關鍵字左側的數都比關鍵字小, 右側的都大於等於關鍵字( 左右兩側的序列依然是無序的) , 然後 將左側的序列按照同樣的方法進行排序, 將右側序列也按照同樣的方法排序, 已達到整個序列有序。
詳解的傳送門:快速排序
void
quick_sort
(int arry,
int left,
int right)
} arry[left]
= arry[i]
; arry[i]
= pivot;
quick_sort
(arry, left, i -1)
;quick_sort
(arry, i +
1, right)
;}
時間複雜度:o(nlog(n)),
空間複雜度:o(n)
堆排序( heapsort) 是指利用堆這種資料結構所設計的一種排序演算法。 堆積是乙個近似完全二叉樹的結構, 並同時滿足堆積的性質: 即子結點的鍵值或索引總是小於( 或者大於) 它的父節點。
void
heap_just
(int a,
int root,
int heap_size)
}void
build_heap
(int a,
int n)
}void
heap_sort
(int a,
int n)
}
時間複雜度:o(nlog(n))
桶排序 (bucket sort)或所謂的箱排序, 是乙個排序演算法, 工作的原理是將陣列分到有限數量的桶子裡。 每個桶子再個別排序( 有可能再使用別的排序演算法或是以遞迴方式繼續使用桶排序進行排序) 。 桶排序是穩定的, 且在大多數情況下常見排序裡最快的一種,比快排還要快, 缺點是非常耗空間,基本上是最耗空間的一種排序算
法, 而且只能在某些情形下使用。
時間複雜度:o(n)
歸併排序是一種穩定的演算法, 採用分治的思想, 有序的子串行合併得到有序序列。
實現步驟:
將序列分成長度為 n/2的兩部分
對於左右兩部分採用分治的方法得到有序序列
將左右兩個有序序列合併得到整個有序序列
void
arry_add
(int arry,
int left,
int mid,
int right)
else
}while
(i <= mid)
while
(j <= right)
for(i =
0; i < k; i++)}
void
merge_sort
(int arry,
int left,
int right)
時間複雜度:o(nlog(n))
二分( 折半) 插入( binary insert sort)排序是一種在直接插入排序演算法上進行小改動的排序演算法。 其與直接排序演算法最大的區別在於查詢插入位置時使用的是二分查詢的方式, 在速度上有一定提公升。
void
binary_insert_sort
(int arry,
int first,
int end)
else
}int key = arry[i]
;for
(int j = i; j > high +
1; j--
) arry[high +1]
= key;
}}
希爾排序, 也稱遞減增量排序演算法, 因dl. shell於2023年提出而得名, 是插入排序的一種高速而穩定的改進版本。
實現步驟:
先取乙個小於n的整數d1作為第乙個增量, 把檔案的全部記錄分成d1個組。
所有距離為d1的倍數的記錄放在同乙個組中, 在各組內進行直接插入排序。
取第二個增量d2直至所取的增量dt=1, 即所有記錄放在同一組中進行直接插入排序為止。
具體詳解的傳送門:希爾排序
void
shell_sort
(int arry,
int left,
int right)
while
(gep >=1)
arry[j + gep]
= temp;
} gep =
(gep -1)
/2;//增量減少
}}
時間複雜度:小於o(n^2)
雞尾酒排序等於是氣泡排序的輕微變形。 不同的地方在於從低到高然後從高到低,而氣泡排序則僅從低到高去比較序列裡的每個元素。 他可以得到比氣泡排序稍微好一點的效能, 原因是氣泡排序只從乙個方向進行比對(由低到高), 每次迴圈只移動乙個專案。
void
cocktail_sort
(int arry,
int left,
int right)
} isswap =
false
; j--
;for
(int k = j; k > i; k--)}
i++;}
while
(i <= j && isswap)
;}
時間複雜度:小於o(n^2)
計數排序(counting sort)是一種穩定的排序演算法。 計數排序使用乙個額外的陣列c,其中第i個元素是待排序陣列a中值等於i的元素的個數。 然後根據陣列c來將a中的元素排到正確的位置。 它只能對整數進行排序。
實現步驟:
找出待排序的陣列中最大和最小的元素。
統計陣列中每個值為i的元素出現的次數, 存入陣列c的第i項。
對所有的計數累加( 從c中的第乙個元素開始, 每一項和前一項相加) 。
反向填充目標陣列: 將每個元素i放在新陣列的第c(i)項, 每放乙個元素就將c(i)減去1 。
超詳細**+優化的傳送門:計數排序
資料結構 排序演算法詳解(面試必備)
對於各個排序的c 或者c的程式設計實現網上很容易找到,也有不少的帖子對這這些排序有總結,看了很多好多沒有將例子的過程寫清楚,僅僅是寫了排序思想或者排序過程很簡陋,不詳細。1 插入排序 o n 2 插入排序是一種最簡單直觀的排序演算法,它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後...
面試必備 經典演算法動畫解析之氣泡排序
哈嘍,我是程式設計師大鵬。最近在招聘過程中,發現好多小夥伴最基礎的一些演算法回答,接下來會做乙個系列,把基礎的排序等演算法採用動畫的形式做解析。這是第一篇氣泡排序。氣泡排序 bubble sort 是一種交換排序,基本思想是兩兩比較相鄰記錄,如果逆序則進行交換,直到沒有逆序的記錄為止。冒泡演算法有很...
排序演算法小結
1 快速排序 quicksort 快速排序是乙個就地排序,分而治之,大規模遞迴的演算法。從本質上來說,它是歸併排序的就地版本。快速排序可以由下面四步組成。1 如果不多於1個資料,直接返回。2 一般選擇序列最左邊的值作為支點資料。3 將序列分成2部分,一部分都大於支點資料,另外一部分都小於支點資料。4...