1.常見排序
2.選擇排序
??選擇排序是一種簡單但不高效的排序算法,其基本思想是從待排序的數(shù)據(jù)中選擇最?。ɑ蜃畲螅┑脑胤诺揭雅判虻臄?shù)據(jù)末尾。具體操作步驟如下:
(1)找到數(shù)據(jù)中最小的元素,并把它交換到第一個位置;
(2)在剩下未排序的元素中找到最小的元素,并把它交換到已排序數(shù)據(jù)的末尾;
(3)重復(fù)第2步,直到所有元素都排好序。
??在選擇排序的實現(xiàn)中,需要使用兩個指針:一個指向當前掃描的區(qū)域的起始位置,另一個指向未排序區(qū)域的起始位置。通過交換找到每次掃描區(qū)域內(nèi)的最小元素,能夠確保每次掃描后已排序區(qū)域變大、未排序區(qū)域變小。
??選擇排序算法的時間復(fù)雜度為O(n^2),不適合處理大量數(shù)據(jù)。
選擇排序的基本思想:
??總結(jié):是每一次從待排序的數(shù)據(jù)元素中選出最?。ɑ蜃畲螅┑囊粋€元素,存放在序列的起始位置,直到全部待排序的數(shù)據(jù)元素排完 。
2.1直接選擇排序
?
直接選擇排序的實現(xiàn)思想:
(1)在元素集合array[i]–array[n-1]中選擇關(guān)鍵碼最大(小)的數(shù)據(jù)元素;
(2)若它不是這組元素中的最后一個(第一個)元素,則將它與這組元素中的最后一個(第一個)元素交換;
(3)在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重復(fù)上述步驟,直到集合剩余1個元素。
?
直接選擇排序的實現(xiàn):
??算法中使用了兩個指針left和right,它們分別指向當前待排序區(qū)間的左右端點。
??在循環(huán)處理待排序區(qū)間的時候,算法首先在當前區(qū)間中查找最小和最大的元素,使用mini和maxi分別記錄這兩個位置。
??然后通過交換操作,把最小元素交換到當前待排序區(qū)間的最左邊,把最大元素交換到最右邊。
??最后通過更新left和right的位置來縮小待排序區(qū)間的范圍,直到排序完成。
??其中Swap函數(shù)是一個交換兩個整數(shù)變量值的函數(shù),實現(xiàn)了傳入兩個指針并利用中間變量進行交換的操作。
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void SelectSort(int* a, int n)
{
int left = 0, right = n - 1;
while (left < right)
{
int mini = left, maxi = left;
for (int i = left + 1; i <= right; i++)
{
if (a[i] < a[mini])
{
mini = i;
}
if (a[i] > a[maxi])
{
maxi = i;
}
}
Swap(&a[left], &a[mini]);
if (left == maxi)
{
maxi = mini;
}
Swap(&a[right], &a[maxi]);
left++;
right--;
}
}
直接選擇排序的特性總結(jié):
(1)直接選擇排序思考非常好理解,但是效率不是很好。實際中很少使用
(2)時間復(fù)雜度:O(N^2)
(3)空間復(fù)雜度:O(1)
(4)穩(wěn)定性:不穩(wěn)定
?
2.2堆排序
??堆排序(Heap Sort)是一種基于堆數(shù)據(jù)結(jié)構(gòu)的排序算法,它是選擇排序的一種優(yōu)化。堆是一種完全二叉樹,分為大根堆和小根堆兩種。
??大根堆的定義是,每個結(jié)點的值都不大于其父節(jié)點的值,根結(jié)點是最大值。
??小根堆的定義是,每個結(jié)點的值都不小于其父節(jié)點的值,根結(jié)點是最小值。
堆排序的流程如下:
(1)構(gòu)建大根堆/小根堆;
(2)將堆頂元素輸出,然后將堆重新調(diào)整為大根堆/小根堆;
(3)重復(fù)步驟2,直到堆中所有元素都已排序。
??具體實現(xiàn)時,可以使用數(shù)組來表示堆,對于一個下標為i的結(jié)點,其左子節(jié)點為2i+1,右子節(jié)點為2i+2,其父節(jié)點為(i-1)/2。
??堆排序的時間復(fù)雜度為O(nlogn),其中n為待排序數(shù)組的長度。堆排序是一種原地排序算法,不需要額外的輔助空間,而且由于堆是一種數(shù)據(jù)結(jié)構(gòu),可以方便地支持動態(tài)的插入和刪除操作,因此應(yīng)用范圍比較廣泛。
堆排序的實現(xiàn)思想:
??堆排序(Heapsort)是指利用堆積樹(堆)這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法,它是選擇排序的一種。它是通過堆來進行選擇數(shù)據(jù)。需要注意的是排升序要建大堆,排降序建小堆。
堆排序的實現(xiàn):
??算法中首先需要建立以數(shù)組中的元素為節(jié)點的大根堆,建堆操作的時間復(fù)雜度為O(n)。
??然后,將大根堆中最后一個節(jié)點與堆頂元素交換,再重新對交換后的堆進行調(diào)整,以使其滿足大根堆的性質(zhì),并將已排好序的元素一直輸出至堆頂,直到所有元素都已排好序。
??具體實現(xiàn)中,利用函數(shù)AdjustDown來對堆進行向下調(diào)整,以使得當前節(jié)點滿足大根堆/小根堆的性質(zhì)。此函數(shù)接受三個參數(shù):待調(diào)整的堆,堆的長度以及需要調(diào)整的節(jié)點。在函數(shù)中,使用child標記當前節(jié)點的左孩子節(jié)點,若右孩子節(jié)點的值更大,則令child等于右孩子節(jié)點的下標;接著判斷child和parent的值,若符合堆的性質(zhì),則結(jié)束調(diào)整,否則交換兩個節(jié)點的值,并向下繼續(xù)調(diào)整。
??在堆排序算法中,最需要注意的是對于任意一個元素,它的左右子樹都必須滿足大根堆/小根堆的性質(zhì)。
// 左右子樹都是大堆/小堆
void AdjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
// 選出左右孩子中大的那一個
if (child + 1 < n && a[child + 1] > a[child])
{
++child;
}
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* a, int n)
{
// 建堆 -- 向下調(diào)整建堆
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
int end = n - 1;
while (end > 0)
{
Swap(&a[end], &a[0]);
AdjustDown(a, end, 0);
--end;
}
}
堆排序的特性總結(jié):
(1)堆排序使用堆來選數(shù),效率就高了很多
(2)時間復(fù)雜度:O(N*logN)
(3)空間復(fù)雜度:O(1)
(4)穩(wěn)定性:不穩(wěn)定
?
3.交換排序
??基本思想:所謂交換,就是根據(jù)序列中兩個記錄鍵值的比較結(jié)果來對換這兩個記錄在序列中的位置,交換排序的特點是:將鍵值較大的記錄向序列的尾部移動,鍵值較小的記錄向序列的前部移動。
3.1冒泡排序
??冒泡排序(Bubble Sort)是一種簡單的排序算法。
??其基本思路是從待排序的第一個元素開始依次比較相鄰的兩個元素的大小。若前面的元素大于后面的元素,則交換兩個元素的位置,這樣較大的元素就會像氣泡一樣不斷向上“浮動”,至多經(jīng)過n-1次排序后就可以將最大的元素放置在最后一個位置上,從而完成第一輪冒泡排序。
??然后,在進行第二輪排序時,對除了最后一個已排好序的元素之外的子序列依次進行冒泡排序,這樣第二輪的冒泡排序可以把次大的元素交換到倒數(shù)第二個位置。
??以此類推,直到所有元素均已排序完畢。
??冒泡排序算法的平均時間復(fù)雜度為 O(n^2),其空間復(fù)雜度為O(1),由于其實現(xiàn)簡單,代碼易懂,因此常用于排序元素較少的列表,對于大規(guī)模的數(shù)據(jù)集,冒泡排序一般不是最優(yōu)選擇。
冒泡排序的實現(xiàn):
??算法中使用兩重循環(huán),外層循環(huán)j控制排序次數(shù),內(nèi)層循環(huán)i控制每一次排序中需要比較的相鄰元素位置。
??具體實現(xiàn)中,使用if語句判斷相鄰元素的大小順序,并交換這兩個元素的位置。
??在排序過程中,待排序的序列不斷地縮小,即外層循環(huán)的次數(shù)逐漸減小,因為每一輪的比較都會讓本輪的待比較元素中最大的元素到達本輪的最后位置。因此,當經(jīng)過n-1輪排序后,整個序列已經(jīng)有序。
void BubbleSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
for (int i = 1; i < n - j; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
}
}
}
}
冒泡排序的特性總結(jié):
(1)冒泡排序是一種非常容易理解的排序
(2) 時間復(fù)雜度:O(N^2)
(3)空間復(fù)雜度:O(1)
(4)穩(wěn)定性:穩(wěn)定文章來源:http://www.zghlxwxcb.cn/news/detail-763911.html
這些就是數(shù)據(jù)結(jié)構(gòu)中有關(guān)直接選擇排序、堆排序和冒泡排序的簡單介紹了??
如有錯誤?望指正,最后祝大家學(xué)習(xí)進步?天天開心???文章來源地址http://www.zghlxwxcb.cn/news/detail-763911.html
到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】常見排序算法——常見排序介紹、選擇排序(直接選擇排序、堆排序)交換排序(冒泡排序)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!