最简单的排序:
冒泡排序:
一种交换排序,算法的思想是:两两交换相邻记录的关键字,如果反序则交换,直到不存在反序的记录为止
void sort(int *a ,int num)
{
if(a==NULL||num<1)
return ;
int i,j;
for(i=0;i<num-1;i++)
for(j=num-1;j>i;j--)
if(a[j]<a[j-1])
swap(a+j,a+j-1);
}
冒泡排序的优化:
试想一种情况,当一个数列是这样子的:{2,1,3,4,5,6,7,8,9},经过一次冒泡排序之后会变成这样子:{1,2,3,4,5,6,7,8,9},如此可见,下面已经没有比较的必要了,所以这里存在着一种优化的可能,我们需要一个标志位,来记录是否在排序过程中发生过交换,如果未发生交换,则证明已经有序,则不需要再进行交换。
void sort2(int* a,int num)
{
if(a==NULL||num<1)
return ;
bool flag=true;
int i,j;
for(i=0;i<num-1&&flag;i++)
{
flag=false;
for(j=num-1;j>i;j--)
if(a[j]>a[j-1])
{
flag=true;
swap(a+j,a+j-1);
}
}
}
简单选择排序:
简单选择排序是指:假设0到i已经有序,在剩下的元素中选择最小的元素与第I+1位置上的元素进行交换
void sort(int* a,int num)
{
if(a==NULL||num<=0)
return ;
int i,k,minindex;
for(i=0;i<num-1;i++)
{
minindex=i;
for(k=i+1;k<num;k++)
if(a[minindex]<a[k])
k=minindex;
if(minindex!=i)
swap(a+i,a+minindex);
}
}
直接插入排序: 直接插入排序不是选择在待排序的元素中选择最小值,而是将待排序的元素放入已经排序的数组中的正确的位置
void insertsort(int *a ,int num)
{
if(a==NULL||num<=0)
return ;
int i,j,temp;
for(i=1;i<num;i++)
{
temp=a[i];
for(j=i;j>0;j--)
{
if(a[j-1]>temp)
a[j]=a[j-1];
else
break;
}
a[j]=temp;
}
}
希尔排序:这个排序就是定义一个间距 distance,将每隔distance间距的子数组当成一个小数组,对其进行直接插入排序,然后将间距逐渐的减小,对于每个减小的间距使用上述同样的方法,直到最后的间距为1,这个时候就是直接插入排序,
void shellsort(int *a,int num)
{
if(a==NULL||num<=0)
return ;
int distance=num;
int i,j,temp;
do{
distance=distance/3+1;
for(i=distance;i<num;i++)
{
if(a[i-distance]>a[i])
{
temp=a[i];
for(j=i;j>0;j-=distance)
{
if(a[j-distance]>temp)
a[j]=a[j-distance];
else
break;
}
a[j]=temp;
}
}
}while(distance>1);
}
堆排序:堆排序是利用完全二叉树进行排序,同时这种完全二叉树有种特性,(因为我们是按照从小到大进行排序的)既是:所有的父节点的值都小于子节点的值(如果子节点存在的话),这样不难看出最小的值一定是在根节点,我们利用这个性质可以进行排序
堆排序中存在着两个重要的过程,就是上虑和下虑的过程,前者用来当Heap(1,n-1)时建立Heap(1,n),后者用来当删除堆顶元素时重新建立堆的过程,
下面是代码片段:
注意:这里的下标都是从1开始的,这样在求子节点的时候很好计算
void siftdown(int *a,int i,int num)
{
int child;
int temp=a[i];
int j;
for(j=i;j*2<=num;)
{
child=2*j;
if(child+1<=num&&a[child+1]<a[child])
child++;
if(a[child]<temp)
{
a[j]=a[child];
j=child;
}
else
break;
}
a[j]=temp;
}
void siftup(int* a,int num)
{
int temp=a[num];
int i=num;
for(;1<=i/2;)
{
if(temp<a[i/2])
{
a[i]=a[i/2];
i>>1;
}
else
break;
}
a[i]=temp;
}
上面的是上虑和下虑的过程,
下面是建堆和进行堆排序的过程
void BuildHeap(int*a,int num)
{
int i;
for(i=2;i<=num;i++)
siftup(a,i);//调用上虑进行建队
}
void HeapSort(int *a,int num)
{
BuildHeap(a,num);
int i=num;
while(i>=1)
{
printf("%d ",a[1]);
a[1]=a[i];
i--;
if(i>=1)
siftdown(a,1,i);//调整进行重新建队
else
break;
}
}
归排和快排明天再说