八種排序的簡單實現
阿新 • • 發佈:2018-11-08
氣泡排序及優化,參考匈牙利氣泡排序舞蹈
//冒泡遞迴寫法 void f0(int a[], int len) { if (len > 1) { int Loop = 0; for (int i = 0; i < len - 1; i++) { Loop++; if (a[i] > a[i + 1]) { swap(a[i], a[i + 1]); Loop = 0; } } f0(a, len - 1 - Loop); } } //迴圈寫法 void f1(int a[], int len) { for (int i = len - 1; i >= 0; i--) { int Loop = 0; for (int j = 0; j < i; j++) { if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); Loop = 0; } else { Loop++; } } i -= Loop; } }
選擇排序,每一趟把最大或者最小的元素放到最後
//遞迴 void f2(int a[], int len) { if (len > 1) { int max = a[0]; int index = 0; for (int i = 0; i < len; i++) { if (a[i] > max) { index = i; max = a[i]; } } swap(a[index], a[len - 1]); f2(a, len - 1); } } //迴圈 void f3(int a[], int len) { for (int i = len - 1; i >= 0; i--) { int max = a[0]; int index = 0; for (int j = 0; j <= i; j++) { if (a[j] > max) { index = j; max = a[j]; } } swap(a[i], a[index]); } }
插入排序,將前面的n個數視為已排好序,然後將第n+1個數插入到前面的正確位置
//遞迴 void f4(int a[], int sorted, int len) { if (len != sorted + 1) { for (int i = sorted + 1; i >= 1 && a[i] < a[i - 1]; i--) { swap(a[i], a[i - 1]); } f4(a, sorted + 1, len); } } //迴圈 void f5(int a[], int len) { for (int i = 1; i < len; i++) { for (int j = i; j >= 1 && a[j] < a[j - 1]; j--) { swap(a[j], a[j - 1]); } } }
歸併排序,將兩端已排好序的序列合併,優化見另一篇博文
void f6(int a[], int len)
{
if (len > 1)
{
f6(a, len / 2);
f6(a + len / 2, len - len / 2);
int b[len];
int cnt = 0;
int start1 = 0, end1 = len / 2;
int start2 = len / 2, end2 = len;
while (start1 < end1 && start2 < end2)
{
if (a[start1] < a[start2])
{
b[cnt++] = a[start1++];
}
else
{
b[cnt++] = a[start2++];
}
}
while (start1 < end1)
{
b[cnt++] = a[start1++];
}
while (start2 < end2)
{
b[cnt++] = a[start2++];
}
for (int i = 0; i < len; i++)
{
a[i] = b[i];
}
}
}
快速排序,以第1個數為參照,找到其正確位置,且讓其前面的數比參照小,後面的數比參照大
//快排
void f7(int a[], int len)
{
if (len > 1)
{
int key = a[0];
int l = 0, r = len - 1;
while (l < r)
{
while (l < r && a[r] > key)
{
r--;
}
a[l] = a[r];
while (l < r && a[l] < key)
{
l++;
}
a[r] = a[l];
}
a[l] = key;
f7(a, l);
f7(a + l + 1, len - 1 - l);
}
}
堆排序,首先建堆,從最後一個葉子節點開始,往前修正,建堆後最大的元素在堆頂。交換堆頂與最後一個元素,len--,修正堆頂
//修正堆中索引為index的元素
void update_heap(int a[], int index, int len)
{
while (index * 2 < len)
{
int ch = 2 * index;
if (ch + 1 < len && a[ch + 1] > a[ch])
{
ch++;
}
if (a[ch] > a[index])
{
swap(a[ch], a[index]);
index = ch;
}
else
{
break;
}
}
}
//建堆,交換,修正
void f8(int a[], int len)
{
for (int i = len / 2 - 1; i >= 0; i--)
{
update_heap(a, i, len);
}
for (int i = len - 1; i >= 1; i--)
{
swap(a[i], a[0]);
update_heap(a, 0, i);
}
}
基數排序:按照個位數依次進隊,然後出隊放回陣列,按照十位數依次進隊,然後出隊放回陣列...
//基數排序
void f9(int a[], int len)
{
queue<int> q[10];
int q0_size = 0;
int m = 1;
while (q0_size != len)
{
for (int i = 0; i < len; i++)
{
int digit = (a[i] / m) % 10;
q[digit].push(a[i]);
}
q0_size = (int)q[0].size();
int cnt = 0;
for (int i = 0; i < 10; i++)
{
while (!q[i].empty())
{
int temp = q[i].front();
q[i].pop();
a[cnt++] = temp;
}
}
m *= 10;
}
}
希爾排序:增量縮小的插入排序
//希爾排序
void f10(int a[], int len)
{
for (int gap = len / 2; gap > 0; gap /= 2)
{
for (int j = gap; j < len; j++)
{
for (int i = j; i - gap >= 0 && a[i] < a[i - gap]; i -= gap)
{
swap(a[i], a[i - gap]);
}
}
}
}
main函式
int main()
{
int a[10] = {4, 2, 5, 6, 1, 0, 3, 7, 8, 9};
f0(a, 10);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
putchar(10);
return 0;
}
前三種簡單排序:O(n^2),選擇排序不穩定,其它穩定
中間三種好的排序:O(nlogn), 歸併排序穩定,其它不穩定
最後兩種,希爾不穩定,基數穩定