我们学习了最基础的三种排序,它们都有个共同点,就是时间复杂度都是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),所以在科学界不断的努力下,排序算法的时间复杂度还是可以改变的嘛!!!