我們學習了最基礎的三種排序,它們都有個共同點,就是時間複雜度都是O(n^2),
在long long ago,科學家們以爲排序時間複雜度已經到了極限了,不可能存在低於O(n^2)
的排序,但是呢!有個傢伙叫希爾的。。。。。(此處略去1W字),然後希爾排序就出現了,
希爾排序的本質還是插入排序(什麼?插入排序,好熟悉啊!),前面我們學了插入排序,
那麼這個希爾到底做了什麼使它的時間複雜度降低到O(n^2)呢?閒話少扯,上代碼。
#include <stdio.h>
#include <stdlib.h>
void print(int array[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ",array[i]);
}
printf("\n");
}
void swap(int array[], int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
void ShellSort(int array[], int len)
{
int i = 0;
int j = 0;
int k = -1;
int temp = -1;
int gap = 0;
do
{
gap = gap / 3 + 1;
for (i = gap; i < len; i += gap)
{
k = i;
temp = array[k];
for (j = i - gap; (j >= 0) && (array[j] >= temp); j--)
{
array[j + gap] = array[j];
k = j;
}
array[k] = temp;
}
} while(gap > 1);
}
int main(int argc, char *argv[])
{
int a[] = {22,44,11,66,77,44,33};
int len = sizeof(a) / sizeof(int);
print(a, len);
ShellSort(a, len);
print(a, len);
system("PAUSE");
return 0;
}
是不是挺簡單的,希爾排序的主要技巧是在gap的設計,但gap具體除以多少暫時還沒有規定,
你把gap設爲1,那就是最壞的情況,也就是成了插入排序。
下面我們來說下項目中常用到的快速排序,在希爾突破了O(n^2)之後,很多科學家也加入研究中,
所以也就有了快速排序。快速排序它很巧妙的把遞歸應用到裏面,在第一次查找的時候,找到一個元素,
這個元素左邊都是小於它,右邊都是大於它,所以第一個元素的位置就確定了,然後左邊和右邊依次遞歸,
整個算法實現非常巧妙,不得不佩服啊!上代碼。
#include <stdio.h>
#include <stdlib.h>
void print(int array[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ",array[i]);
}
printf("\n");
}
void swap(int array[], int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
int Postition(int array[], int low, int high)
{
int pv = array[low];
while (low < high)
{
while ((low < high) && (array[high] >= pv))
{
high--;
}
swap(array, low, high);
while ((low < high) && (array[low] <= pv))
{
low++;
}
swap(array, low, high);
}
array[low] = pv;
return low;
}
void QSort(int array[], int low, int high)
{
if (low < high)
{
int pos = Postition(array, low, high);
QSort(array, low, pos - 1);
QSort(array, pos + 1, high);
}
}
void QuickSort(int array[], int len)
{
QSort(array, 0, len - 1);
}
int main(int argc, char *argv[])
{
int a[] = {22,44,11,66,77,44,33};
int len = sizeof(a) / sizeof(int);
print(a, len);
QuickSort(a, len);
print(a, len);
system("PAUSE");
return 0;
}
看明白了嗎?是不是言簡意賅,好了下面我們介紹下歸併排序,爲什麼會存在歸併排序呢?
主要是因爲希爾排序和快速排序不是穩定的排序,在操作過程中有大量的數據移動,所以,
就產生了一種叫歸併排序的東東,那麼什麼是歸併排序呢?簡單的說就是,把一組數據,
分成幾個已經排好的數組,然後把他們合併成一個數組(百度吧!這個一下數不清楚)
好了,show time!
#include <stdio.h>
#include <stdlib.h>
void print(int array[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ",array[i]);
}
printf("\n");
}
void Merge(int src[], int dest[], int low, int mid, int high)
{
int i = low;
int j = mid + 1;
int k = low;
while ((i <= mid) && (j <= high))
{
if (src[i] < src[j])
{
dest[k++] = src[i++];
}
else
{
dest[k++] = src[j++];
}
}
while (i <= mid)
{
dest[k++] = src[i++];
}
while (j <= high)
{
dest[k++] = src[j++];
}
}
void MSort(int src[], int dest[], int low, int high, int max)
{
if (low == high)
{
dest[low] = src[low];
}
else
{
int mid = (low + high) / 2;
int* space = (int*)malloc(sizeof(int) * max);
if (space != NULL)
{
MSort(src, space, low, mid, max);
MSort(src, space, mid + 1, high, max);
Merge(space, dest, low, mid, high);
}
free(space);
}
}
void MergeSort(int array[], int len)
{
MSort(array, array, 0, len - 1, len);
}
int main(int argc, char *argv[])
{
int a[] = {22,44,11,66,77,44,33};
int len = sizeof(a) / sizeof(int);
print(a, len);
MergeSort(a, len);
print(a, len);
system("PAUSE");
return 0;
}
是不是跟快速排序有點像呢?但是它保證穩定性的前提下,犧牲了空間,就是每次分組之後申請的堆空間。
上述三種排序的時間複雜度都是O(nlogn),所以在科學界不斷的努力下,排序算法的時間複雜度還是可以改變的嘛!!!