所有排序的总结:
1、 插入排序
插入排序是最简单最直观的排序算法了,它的依据是:遍历到第N个元素的时候前面的N-1个元素已经是排序好的了,那么就查找前面的N-1个元素把这第N个元素放在合适的位置,如此下去直到遍历完序列的元素为止.
插入排序是最简单最直观的排序算法了,它的依据是:遍历到第N个元素的时候前面的N-1个元素已经是排序好的了,那么就查找前面的N-1个元素把这第N个元素放在合适的位置,如此下去直到遍历完序列的元素为止.
算法的复杂度也是简单的,排序第一个需要1的复杂度,排序第二个需要2的复杂度,因此整个的复杂度就是
1 + 2 + 3 + ... + N = O(N ^ 2)的复杂度.
// 插入排序
void InsertSort(int array[], int length)
{
int i, j, key;
for (i = 1; i < length; i++)
{
key = array[i];
// 把i之前大于array[i]的数据向后移动
for (j = i - 1; j >= 0 && array[j] > key; j--)
{
array[j + 1] = array[j];
}
// 在合适位置安放当前元素
array[j + 1] = key;
}
}
2、选择排序:
每次确定一个数位,这个数位是后面所有数的最小值放到这个位置
Void SelectInsert(int *arr)
{ int i,j;
int min,index;
For(i=0;i<n-1;i++)
{
For(j=i+1,index=j,min=arr[j]; j<n; j++)
{
If( arr[j]<min )
{ min=arr[j] ;
index=j;
}
}
int temp=arr[i];
arr[i]=arr[index];
arr[index]=temp;
}
}
3、堆排序:
//HEAP SORT 堆排序,用一个二插堆,大根堆即可
//heap[0]是临时元素,作临时变量用途;heap[1 -- n]是实际的大根堆的数据内存空间
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
const int MAX=100004;
void swap(int &a,int &b) //注意传引用
{
a^=b;
b^=a;
a^=b;
}
void buildheap(int* arr,int len) //O( N*Lg(N) )
{
int i,j,t;
for( i=len/2;i>=1;i-- ) //从底往上进行构造
{
j=i;
while(j<=len)
{
t=arr[j];
if( j*2<=len && t < arr[j*2] )
t=arr[j*2];
if( (j*2+1)<=len && t < arr[j*2+1] )
t=arr[j*2+1];
if( t==arr[j*2] )
{ swap( arr[j],arr[j*2] );
j=j*2;
continue;
}
else if( t==arr[j*2+1] )
{ swap( arr[j],arr[j*2+1] );
j=j*2+1;
continue;
}
else
break; //退出while
}
}
}
void adjustheap(int* arr,int l)
{
int i,t;
i=1;
while(i<=l)
{
t=arr[i];
if( (i*2)<=l && t < arr[i*2] )
t=arr[i*2];
if( (i*2+1)<=l && t < arr[i*2+1] )
t=arr[i*2+1];
if( t==arr[i*2] )
{ swap( arr[i],arr[i*2] );
i=i*2;
continue;
}
else if( t==arr[i*2+1] )
{ swap( arr[i],arr[i*2+1] );
i=i*2+1;
continue;
}
else
break; //退出while
}
}
void heapsort(int* arr,int len)
{
int i;
buildheap(arr,len);
for(i=len;i>=2;i--)
{
swap(arr[1],arr[i]);
adjustheap(arr,i-1); //是i-1这个参数,很变态很无敌
}
for(i=1;i<len;i++)
printf("%d ",arr[i]);
printf("%d/n",arr[i]);
}
int main()
{
int arr[MAX];
srand(time(NULL));
for(int i=0;i<100;i++)
arr[i+1]=rand()%100;
heapsort(arr,100);
getchar();
return 0;
}
4、 归并排序: //N*lg(N) 复杂度,因为一层整个叶子是 //N,然后一共有lg(N)层
int temp[MAX]; //因为有归并的过程,所以不是内排序,需要另外开辟这个存储数组空间
void merge(int* arr,int start,int mid,int end)
{ //start~mid是排序好的mid+1~end也是排序好的,只要把这两部分合并起来即可
int n1=mid-start+1;
int n2=end-mid;
int i,cnt;
int i1=start,i2=mid+1;
for(i=start,cnt=0;i<=end;i++)
{
if( i1>mid )
{ temp[cnt++]=arr[i2];
i2++;
continue;
}
if( i2>end )
{
temp[cnt++]=arr[i1];
i1++;
continue;
}
if( arr[i1]>arr[i2] )
{
temp[cnt++]=arr[i2];
i2++;
}
else
{
temp[cnt++]=arr[i1];
i1++;
}
}
for(i=start,cnt=0;i<=end;i++)
arr[i]=temp[cnt++];
}
void mergesort(int* arr,int start,int end) //归并排序
{
if(start<end) //==的时候即不用继续mergesort
{
int mid=(start+end)>>1;
mergesort(arr,start,mid);
mergesort(arr,mid+1,end);
merge(arr,start,mid,end);
}
}
5、 快速排序:QSORT 注意那个桶倒来倒去的过程和办法即可
6、冒泡排序有个优化就是if(a[i]>a[i+1])的时候记录 i 的值temp,内层的循环只要循环到这个temp值即可,因为后面的是有序的。
总结上述的排序算法:
稳定的讨论就是说按照同样的数字进行原序的排序
自然选择排序和插入排序太慢,用起来不爽
那么就讨论下 归并,堆排和快排
快排有退化 就是O(N^2) 但是不用第一个,而是每次用随机算法选择数能改进这个算法的最坏复杂度,而且快排不稳定…
归并排序,是非内部排序,需要另外开辟空间处理,但是是稳定的,用来处理逆序数很强大
而堆排 是不稳定的,但是是内部排序,并且没退化,处理大数据来说非常好的