本文總結了頻繁出現在面試題中的排序算法,並提供了java和python兩種語言實現,作爲自己複習的總結,也希望對其他找工作的朋友們有所幫助。
一、快速排序:
快速排序通常情況下,是用於排序的最佳的實用選擇。這是因爲其平均性能相當好:期望的運行時間爲O(nlogn),且O(nlogn)記號中隱藏的常數因子很小。另外,它還能夠進行就地排序,在虛存環境中也能很好地工作。接下來我們便來好好了解一下快速排序的思想。
1、時間複雜度: best: O(n*logn) average: O(n*logn) worst: O(n^2)
2、空間複雜度: O(logn)
3、算法描述:
像合併排序一樣,快速排序也是基於分支模式的,主要分爲以下三個步驟:分解、解決、合併
4、快速排序的數據結構:
QUICKSORT(A, p, r)
if p<r
then q <- PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
爲排序一個完整的數組A,最初的調用是QUICKSORT(A, 1, length(A))
快速排序算法的關鍵是PARTITION過程,它對子數組A[p...r]進行就地重排:
PARTITION(A,p, r)
x <- A[r]
i <- p-1
for j <- p to r-1
do if A[j]<=x
then i <- i+1
exchange A[i] <-> A[j]
exchange A[i+1] <-> A[r]
return i+1
5、python實現快速排序代碼:
'''
quick_sort
author: fuhongyu
time: 2018-07-27
time complecity: O(nlog(n))
object:15 minutes
'''
def quick_sort(array, l, r):
if l < r:
q = partition(array, l, r)
quick_sort(array, l, q - 1)
quick_sort(array, q + 1, r)
return array
def partition(array, l, r):
x = array[r]
i = l - 1
for j in range(l, r):
if array[j] <= x:
i += 1
array[i], array[j] = array[j], array[i]
array[i + 1], array[r] = array[r], array[i+1]
return i + 1
測試快速排序代碼:
lists = [3,5,1,2,7]
quick_sort(lists, 0, len(lists)-1)
6、java實現快速排序:
package test;
/**
*
* @author FHY
* 實現快速排序
* 2019.6.6
*/
public class QuickSortDemo {
public static void main(String[] args) {
int[] nums = {2,4,1,6,3,8,5};
int n = nums.length;
quickSort(nums, 0, n-1);
for (int i : nums) {
System.out.println(i);
}
}
private static void quickSort(int[] nums, int p, int n) {
if (p>=n) return;
int q = getPartition(nums,p, n);//獲取分區
quickSort(nums, p, q-1);
quickSort(nums, q+1, n);
}
/**
* @param nums 數組
* @param p 要比較的左邊界
* @param r 要比較的右邊界
* @return 返回劃分分區的中間節點
* 將最後一個元素作爲標誌位pivot,通過比較將小於標誌位的元素放到左邊,大於標誌位的放到右邊
*/
private static int getPartition(int[] nums, int p, int r) {
int pivot = nums[r]; //把最後一個元素作爲標誌
int i = p;
for(int j = p; j <= r-1; j++){
if(nums[j] < pivot){
//交換nums[j]和nums[i]
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
}
}
//交換pivot和nums[i]
int temp1 = nums[i];
nums[i] = nums[r];
nums[r] = temp1;
return i;
}
}
二、歸併排序:
1、簡單介紹:歸併排序採取了分治法的思想,在每一層遞歸上都有三個步驟:<1>分解 <2>解決 <3> 合併
2、時間複雜度:best: O(n*logn) average: O(n*logn) worst: O(n*logn)
3、空間複雜度:O(n)
4、合併排序算法數據結構:
MERGE_SORT(A, p, r)
if p < r
then q <- (p+r)/2 # 取下限
MERGE_SORT(A, p, q)
MERGE_SORT(A, q+1, r)
MERGE(A, p, q, r)
5、python實現合併排序算法代碼:
'''
merge_sort
author: fuhongyu
time: 2018-07-27
time complexity: O(n^2)
objective:15 minutes
'''
def merge(a ,b):# 合併兩個list
i = 0
j = 0
result = []
while i<len(a) and j <len(b):
if a[i] < b[j]:
result.append(a[i])
i += 1
else:
result.append(b[j])
j += 1
if i == len(a):
for i in b[j:]:
result.append(i)
else:
for i in a[i:]:
result.append(i)
return result
def merge_sort(lists):
if len(lists) <= 1:
return lists
middle = len(lists)//2
left = merge_sort(lists[:middle])
right = merge_sort(lists[middle:])
return merge(left, right)
測試排序函數:
lists = [3,4,2,6,4,8,3,0,20,34,1,4,56,3]
merge_sort(lists)
6、java代碼實現:
package test;
/**
* @author FHY
* 歸併排序算法實現
* 2019.6.6
*/
public class MergeSortMain {
public static void main(String[] args) {
int[] nums = {2,4,1,6,3,8,5};
int n = nums.length - 1;
merge(nums, 0, n);
for (int i : nums) {
System.out.println(i);
}
}
public static void merge(int[] arr, int start, int end){
if (start >= end)
return;
int mid = start + (end - start)/2;
merge(arr, start, mid);
merge(arr, mid + 1, end);
sort(arr, start, mid, end);
}
private static void sort(int[] arr, int start, int mid, int end) {
int index1 = start;
int index2 = mid + 1;
int[] result = new int[end - start + 1];
int index = 0;
while(index1 <= mid && index2 <= end){
if(arr[index1] <= arr[index2]){
result[index++] = arr[index1++];
}else
result[index++] = arr[index2++];
}
if(index1 <= mid)
result[index++] = arr[index1++];
else if(index2 <= end)
result[index++] = arr[index2++];
for(int i = 0; i < result.length; i++){
arr[start+i] = result[i];
}
}
}
補充:歸併算法,歸即遞歸,並即合併。該算法運行速度很快,但因爲是遞歸算法,故對CPU消耗很大
三、插入排序:
1、簡單介紹:插入排序作爲最基本的入門排序,算法思想最簡單,最容易實現。
該算法是一個就地排序算法,思想是:將數組A中的元素A[1......n]依此插入到已經拍好序的sequenceA中。
2、時間複雜度: best: O(n) average: O(n^2) worst: O(n^2)
3、空間複雜度: O(1)
4、插入排序的數據結構
INSERTION-SORT(A)
for j <- 2 to length[A]
do key <- A[j]
# Insert A[j] into the sorted sequence A[1...j-1].
i <- j-1
while i>0 and A[i]>key
do A[i+1] <- A[i]
i <- i-1
A[i+1] <- key
4、python實現插入排序代碼:
'''
insert_sort
author: fuhongyu
time: 2018-07-27
time compliexity:O(n^2)
objective: 10 minutes
'''
def inser_sort(lists):
for i in range(1,len(lists)):
key = lists[i]
j = i-1
# insert lists[j] into sequence lists
while j >= 0:
if lists[j] > key:
lists[j+1] = lists[j]
lists[j] = key
j -= 1
return lists
5、java代碼實現:待補。。。。。。
四、堆排序:
1、簡單介紹:像合併排序而不像插入排序,堆排序的運行時間是O(n*logn)。像插入排序而不像合併排序,他是一種原地排序算法,在任何時候,數組中只有常數個元素存儲在輸入數組以外。這樣,堆排序就把上述兩種排序的算法的優點結合起來了。
2、時間複雜度: best: O(n*logn) average: O(n*logn) worst: O(n*logn)
3、空間複雜度:O(1)
4、算法說明:堆排序過程主要分爲三步:
1)保持堆的性質:將堆調整爲最大堆:MAX-HEAPIFY(A, i),使i爲根的子樹稱爲最大堆。
2)建堆: BUILD-MAX-HEAPIFY :將一個數組A[1...n]變成一個最大堆。
3)堆排序算法:HEAPSORT(A) : 將數組A進行排序
5、python實現代碼如下:
'''
function:heap sort
author: fuhongyu
time: 2018-07-28
completion:15 minutes
time complecity:O(n*logn)
'''
def max_heap(lists, i, size):
lchild = 2*i
rchild = 2*i+1
max = i
if lchild < size and lists[lchild] > lists[max]:
max = lchild
if rchild < size and lists[rchild] > lists[max]:
max = rchild
if max != i:
lists[i] , lists[max] = lists[max], lists[i]
max_heap(lists, max, size)
def build_heap( lists):
size = len(lists)
for i in range(0, size//2)[::-1]:
max_heap(lists, i, size)
return lists
def heap_sort( lists):
size = len(lists)
lists = build_heap(lists)
print(lists)
for i in range(0, size)[::-1]:
lists[i], lists[0] = lists[0], lists[i]
max_heap(lists, 0 ,i)
print(lists)
測試上面的程序:
lists = [4,1,3,2,16,9,10,14,8,7]
heap_sort(lists)
6、java代碼實現:待補。。。。。。
7、應用:
雖然堆排序算法是一個很漂亮的算法,但在實際中,快速排序的一個好的實現往往優於堆排序。儘管這樣,堆數據結構還是有很大的用處。一個很常見的應用就是:作爲高效的優先級隊列,包括最大優先級隊列和最小優先級隊列,分別對應最大堆和最小堆。
一個堆可以在O(lgn)時間內,支持大小爲n的集合上的任意優先隊列的操作。
五、冒泡排序:
1、簡單說明:冒泡排序的實現非常簡單,時間複雜度大,但是作爲經典的排序算法還是值得一提的。
2、python 實現冒泡排序算法代碼:
'''
bubbling_sort
author: fuhongyu
time: 2018年7月27日
時間複雜度: n^2
目標:5 minutes
'''
def bubblesort(lists):
for i in range(len(lists)-1):
for j in range(i+1 , len(lists)):
if lists[i] > lists[j]:
temp = lists[i]
lists[i] = lists[j]
lists[j] = temp
return lists
3、java代碼實現:待補。。。。。。
總結:
排序算法時間複雜度和空間複雜度比較