資料結構與演算法筆記(十二)排序

2021-10-23 18:19:45 字數 3635 閱讀 6321

就是讓一組無序資料變成有序的過程。 一般預設這裡的有序都是從小到大的排列順序

衡量乙個排序演算法的優劣,主要從三個角度分析:

時間複雜度:包括最好時間複雜度、最快時間複雜度、平均時間複雜度

空間複雜度:如果空間複雜度為1,也叫原地排序

穩定度:是指相等的資料物件,在排序之後,順序能否保持不變

1.原理

從第乙個資料開始,依次比較相鄰元素的大小。如果前者大於後者,則進行交換操作,把大的元素往後交換。通過多輪迭代,直到沒有交換操作為止。

2.效能

氣泡排序最好時間複雜度是 o(n)

氣泡排序最壞時間複雜度是 o(n*n)。

很顯然,當輸入陣列雜亂無章時,它的平均時間複雜度也是 o(n*n)。

氣泡排序不需要額外的空間,所以空間複雜度是 o(1)。氣泡排序過程中,當元素相同時不做交換,所以氣泡排序是穩定的排序演算法

public static void main(string args) ;

system.out.println("原始資料: " + arrays.tostring(arr));

for (int i = 1; i < arr.length; i++)

} }system.out.println("氣泡排序: " + arrays.tostring(arr));

}

1.原理

選取未排序的元素,插入到已排序區間的合適位置,直到未排序區間為空

2.效能

插入排序最好時間複雜度是 o(n)

插入排序最壞時間複雜度則需要 o(n*n)。

插入排序的平均時間複雜度是 o(n*n)。

插入排序不需要開闢額外的空間,所以空間複雜度是 o(1)。

根據上面的例子可以發現,插入排序是穩定的排序演算法

public static void main(string args) ;

system.out.println("原始資料: " + arrays.tostring(arr));

for (int i = 1; i < arr.length; i++) else

} arr[j + 1] = temp;

} system.out.println("插入排序: " + arrays.tostring(arr));

}

插入排序和氣泡排序演算法的異同點:

相同:插入排序和氣泡排序的平均時間複雜度都是 o(n*n),穩定的排序演算法,原地排序。

不同:氣泡排序每輪的交換操作是動態的,所以需要三個賦值操作才能完成;

而插入排序每輪的交換動作會固定待插入的資料,因此只需要一步賦值操作。

1.原理

分治法,首先將陣列不斷二分,直到最後每個部分只包含乙個資料,然後再對每個部分分別金牌排序,最後將排序好的相鄰的兩個部分合併在一起,最後陣列就有序了

public static void main(string args) ;

int tmp = new int[arr.length];

system.out.println("原始資料: " + arrays.tostring(arr));

custommergesort(arr, tmp, 0, arr.length - 1);

system.out.println("歸併排序: " + arrays.tostring(arr));

}public static void custommergesort(int a, int tmp, int start, int end)

}public static void customdoublemerge(int a, int tmp, int left, int mid, int right)

while (p1 <= mid)

tmp[k++] = a[p1++];

while (p2 <= right)

tmp[k++] = a[p2++];

// 複製回原素組

for (int i = left; i <= right; i++)

a[i] = tmp[i];

2.效能

對於歸併排序,它採用了二分的迭代方式,複雜度是 logn。

每次的迭代,需要對兩個有序陣列進行合併,這樣的動作在 o(n) 的時間複雜度下就可以完成。

歸併排序的複雜度就是二者的乘積 o(nlogn)。

同時,它的執行頻次與輸入序列無關,因此,歸併排序最好、最壞、平均時間複雜度都是 o(nlogn)。

空間複雜度方面,由於每次合併的操作都需要開闢基於陣列的臨時記憶體空間,所以空間複雜度為 o(n)。歸併排序合併的時候,相同元素的前後順序不變,所以歸併是穩定的排序演算法。

1.原理

分治法,每輪迭代都會選取陣列中任意乙個資料作為分割槽點,將小於它的元素放在左側,將大於它的元素放在右側,繼續利用分支,直至每個區間縮小為1,則完成排序。

public static void main(string args) ;

system.out.println("原始資料: " + arrays.tostring(arr));

customquicksort(arr, 0, arr.length - 1);

system.out.println("快速排序: " + arrays.tostring(arr));

}public void customquicksort(int arr, int low, int high)

i = low;

j = high;

temp = arr[low];

while (i < j)

// 再看左邊,依次往右遞增

while (temp >= arr[i] && i < j)

t = arr[j];

arr[j] = arr[i];

arr[i] = t;

} arr[low] = arr[i];

arr[i] = temp;

// 遞迴呼叫左半數組

customquicksort(arr, low, j - 1);

// 遞迴呼叫右半陣列

customquicksort(arr, j + 1, high);

}

2.效能

在快排的最好時間的複雜度 o(n*logn)

最壞的時間複雜度 o(n*n)

平均的時間複雜度是 o(n*logn)

快速排序法的空間方面,使用了交換法,因此空間複雜度為 o(1)

快排是不穩定的排序演算法

排序最暴力的方法,時間複雜度是 o(n*n),氣泡排序和插入排序

利用歸併排序就能讓時間複雜度降低到 o(nlogn)。但歸併排序需要額外開闢臨時空間。一方面是為了保證穩定性,另一方面則是在歸併時,由於在陣列中插入元素導致了資料挪移的問題。

為了規避因此而帶來的時間損耗,此時我們採用快速排序。通過交換操作,可以解決插入元素導致的資料挪移問題,而且降低了不必要的空間開銷。但是由於其動態二分的交換資料,導致了由此得出的排序結果並不穩定。

如果對資料規模比較小的資料進行排序,選擇時間複雜度為 o(n*n) 的排序演算法,資料量小,對實際效能影響不大

但對資料規模比較大的資料進行排序,就需要選擇時間複雜度為 o(nlogn) 的排序演算法了。

資料結構與演算法(十二) 計數排序

計數排序是桶排序的乙個特例,即 桶的大小為1。這樣一來,分桶之後,每個桶內部就不需要排序了,只需將不同桶的資料合併到一起,組成排序好的序列。計數排序對資料的要求十分嚴格 找出原始陣列l中最大的元素值max 構造乙個計數陣列count,count的下標為從0到max,儲存的值為原陣列中元素值等於下標的...

資料結構與演算法(十二) 堆排序

對於 堆 我們可以理解為具有以下性質的完全二叉樹 堆排序是利用堆這種資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為o nlogn 它也是不穩定排序。在排序時,一般公升序採用大頂堆,降序採用小頂堆。我們可以看到,層數從小到大,節點的數字是越來越小的,對映到陣列...

資料結構與演算法 排序

排序原理 1.比較相鄰的元素。如果前乙個元素比後乙個元素大,就交換這兩個元素的位置。2.對每一對相鄰元素做同樣的工作,從開始第一對元素到結尾的最後一對元素。最終最後位置的元素就是最大 值。氣泡排序的 實現 public static void sortpop int arr 測試 public st...