演算法與資料結構之美 排序 上

2021-09-25 12:32:49 字數 2083 閱讀 6335

氣泡排序(bubble sort)

插入排序(insertion sort)

選擇排序(selection sort)

解答開篇

本篇部落格將會總結一下冒泡、插入、選擇排序,思考乙個問題就是,插入排序和氣泡排序的時間複雜度都是o(n^2),但是為何在實際軟體開發中更傾向於選擇插入排序?

分析排序演算法的執行效率,主要是從以下幾個方面:

最好情況、最壞情況、平均情況複雜度;

時間複雜度的係數、常數、低階;

比較次數和交換次數;

對於排序演算法的空間複雜度,引入乙個原地排序(sorted in place)的概念,原地排序演算法就是空間複雜度為o(1)的排序演算法;

穩定性,是指待排序的序列中存在值相等的元素,經過排序之後,想等元素之間原有的先後順序不變;

氣泡排序每次只會操作相鄰的兩個資料,看是否滿足大小關係,不滿足就呼喚,一次氣泡排序就會至少讓乙個元素移動到它應該在的位置上,重複n次,就完成了n個資料的排序工作。

上圖為一次氣泡排序的過程,其實氣泡排序還是可以優化的。當某次冒泡操作沒有資料可以交換時,說明已經達到完全有序,不用在執行後序的冒泡操作。

**如下:

public

void

bubblesort

(int

a,int n)}if

(!flag)

break

;//沒有資料交換,提前退出

}}

首先將陣列中的資料分為兩個區間,已排序區間和未排序區間。初始已排序區間只有乙個元素,就是陣列的第乙個元素;插入排序演算法的核心是從未排序區間中選取元素,在已排序區間中找到合適的插入位置將其插入,並保證已排序區間中的資料一直有序,直到未排序的區間中的元素為空;下圖是插入排序的過程;

//插入排序,a表示陣列,n表示陣列大小

public

static

void

insertionsort

(int

a ,int n)

else

} a[j+1]

= value;

}}

選擇排序演算法類似插入排序,將陣列分為已排序區間和未排序區間,但是每次是從未排序區間中找到最小的元素,將其放到已排序的區間的末尾;

//選擇排序,a表示陣列,n表示陣列大小

public

static

void

selectionsort

(int

a,int n)

}//交換

int tmp = a[i]

; a[i]

= a[minindex]

; a[minindex]

= tmp;

}}

從**實現上來看,氣泡排序的資料交換要比插入排序的資料移動要複雜,氣泡排序需要3個賦值操作,而插入排序只需要1個。我們來看這段操作:

氣泡排序中資料的交換操作:

if (a[j] > a[j+1]) 

插入排序中資料的移動操作:

if (a[j] > value) else

我們把執行乙個賦值語句的時間粗略地計為單位時間(unit_time),然後分別用氣泡排序和插入排序對同乙個逆序度是k的陣列進行排序。用氣泡排序,需要k次交換操作,每次需要3個賦值語句,所以交換操作總耗時就是3*k單位時間。而插入排序中資料移動操作只需要k個單位時間雖然氣泡排序和插入排序在時間複雜度上是一樣的,都是o(n2),但是如果我們希望把效能優化做到極致,那肯定首選插入排序。

資料結構與演算法之美 排序(上)

開篇問題的解答請放到最後再看噢 雖然氣泡排序和插入排序演算法的時間複雜度都是o n2 氣泡排序涉及到元素的交換,插入排序涉及到元素的移動,交換次數和移動次數都是相同的,都是原始序列的逆序度。在氣泡排序中,元素的交換要三次賦值語句,而插入排序中元素的移動只需要一次賦值語句。所以若考慮到效能優化到極致,...

資料結構與演算法之排序(上)

對於冒泡這個排序演算法,相信大家都不陌生,所以我們更加深入的來看一下這個演算法,討論一下他的時間複雜度,最好情況是當所有元素都按公升序排列好了,這個時候的時間複雜度是o n 多少個元素就比較了多少次。為了不讓排序無腦的進行下去,我們加了乙個flag標記,排好序便會自動退出。最壞的情況下,都是逆序排的...

資料結構與演算法之美

什麼是資料結構?什麼是演算法 狹義重點 複雜度分析 方法 邊學邊練,適度刷題 複雜度分析 時間複雜度 常見時間複雜度 非多項式量級 非常低效的演算法 空間複雜度 漸進空間複雜度,表示演算法的儲存空間和資料規模的增長關係 最好情況時間複雜度 理想情況的時間複雜度 最壞情況時間複雜度 最糟糕的情況下的時...