1.插入排序:从头开始遍历,当前的和前面的数去比较,如果小的话,插到前面,时间复杂度o(n^2);
#include<stdio.h>
void quik(int array[],int sz)
{
int *arr = array;
int start = 0;
int end = sz-1;
int i = 0;
for(start = 0; start<end; start++)
{
for(i=start; i>=0; i--)
{
int tmp = 0;
if(arr[i+1] < arr[i])
{
tmp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = tmp;
}
}
}
}
2.希尔排序:它是对插入排序的优化,经测得他 的效率是插入排序的100倍左右。
思想:主要是把它分为几组grep,先对它几组几组的来个伪排序,grep越小越接近排好的序列,最后用插入排序
只需要把i++ 变为 i += grep,start +=grep,每次grep= grep/3即可
3.选择排序
思想:每次选一个最小的放在最前面,下面是优化的版本,在选最小的时候,选出一个最大的放在最后面
void sort(int *arr,int sz)
{
int i =0;
int j = 0;
for(i=0; i<sz; i++,sz--)
{
int min = i;
int max = sz-1;
int tmp = 0;
int ret = 0;
for(j=i; j<sz; j++)
{
if(arr[j] < arr[min])
{
min = j;
}
if(arr[j] > arr[max])
max = j;
}
tmp = arr[i];
ret = arr[sz-1];
arr[i] = arr[min];
if(max == i)
max = min;
arr[min] = tmp;
arr[sz-1] = arr[max];
arr[max] = ret;
}
}
快速排序:每次随机产生一个值,把小的放在它左边,大的放在它右边
int oncesort(int *arr,int n,int start,int end)
{
int i = 0;
int index = 0;
int small = start-1;
int tmp = 0;
idnex = rand()%n;
while(index <start || index>end)
index = rand()%n;
tmp = arr[index];
arr[index] = arr[end];
arr[end] = tmp;
for(i=start; i<end; i++)
{
if(arr[i] < arr[end])
{
++small;
if(small != i)
{
int temp = arr[small];
arr[small] = arr[i];
arr[i] = temp;
}
}
}
++small;
tmp = arr[small];
arr[small] =arr[end];
arr[end] = tmp;
return small;
}
void sort(int *arr,int sz,int start,int end)
{
int index = 0;
if(start == end)
return;
index = oncesort(arr,sz,start,end);
if(index>start)
sort(arr,sz,0,index-1);
if(index < end)
sort(arr,sz,index+1,end);
}
堆排序:先以完全二叉树创建一个大堆,然后每次把第一个最大值放到最后,在重新向上调整堆,
void ADjustDown(int *arr,int n ,int root)
{
int parent = root;
int child = root*2+1;
while(child<=n)
{
if(arr[child]<arr[child+1] && child+1<=n)
{
child++;
}
if(arr[child] >arr[parent])
{
int tmp = arr[child];
arr[child] = arr[parent];
arr[parent] = tmp;
parent = child;
child = parent*2+1;
}
else
break;
}
}
void sort(int *arr,int sz)
{
int i =sz;
int end =sz-1;
for(i=(sz-1)/2; i>=0; i--)
{
ADjustDown(arr,sz-1,i);
}
while(end>0)
{
int tmp = arr[0];
arr[0] = arr[end];
arr[end] = tmp;
end--;
ADjustDown(arr,end,0);
}
}
归并:归并的思想和二分查找类似,先把它分成一半然后在各自再分成一半,一直到它们只剩一个值得时候,合并两个数组。
优点:归并是稳定的算法,时间复杂度为O(log2n)
缺点:浪费了O(n)的空间、
void merge(int*arr,int start1,int end1,int start2,int end2,int *tmp)
{
int ret = start1;
int index = start1;
while(start1 <= end1 && start2 <= end2)
{
if(arr[start1] < arr[start2])
{
tmp[index++] = arr[start1++];
}
else
tmp[index++] = arr[start2++];
}
while(start1 <= end1)
{
tmp[index++] = arr[start1++];
}
while(start2 <= end2)
{
tmp[index++] = arr[start2++];
}
memcpy(arr+ret,tmp+ret,sizeof(int)*((end2-ret)+1));
}
void mergesort(int *arr,int start,int end,int *tmp)
{
int mid = start+((end-start)>>1);
if(start == end) // 当只剩一个数的时候开始合并
return;
mergesort(arr,start,mid,tmp);
mergesort(arr,mid+1,end,tmp);
merge(arr,start,mid,mid+1,end,tmp);
}