假设为10个数排序
冒泡排序:
冒泡排序停止交换的条件应该是有一趟排序中没有交换元素 !这样才可以在有序的情况下达到O(n)的时间复杂度。
void Bubble_Sortt(int a[])
{
inti,j,t;
_Boolchange=0;
for(i=9;i>0&&change;i--)//n-1次排序
{
change=false;
for(j=0;j<i;j++)//i次交换
{
if(a[j]>a[j+1])
{
t=a[j+1];
a[j+1]=a[j];
a[j]=t;
change=true;
}
}
}
}
稳定性:稳定
时间复杂度,最坏为O(n2),那就是关键字逆序的情况,因为要做n(n-1)/2次的关键字比较,还有同数量级的记录移动,所以是 O(n2)
最好情况可以是O(n),那就是关键字正序的情况下,此时不用进行交换,只是进行n-1次比较,所以时间复杂度为O(n)
快速排序:
int Partition(int a[],int low,int high)
{
int key=a[low];//注意是a[low]不是a[1],因为以后还要递归调用
while(low<high)
{
while(low<high&&key<a[high])//注意每次比较的对象是key
high--;
a[low]=a[high];
while(low<high&&a[low]<key)
low++;
a[high]=a[low];
}
a[low]=key;//枢轴记录到位
return low;
}
voidQuick_Sort(int a[],int low,int high)
{
int key;
if(low<high)
{
key=Partition(a,low,high);
Quick_Sort(a,key+1,high);
Quick_Sort(a,low,key-1);
}
}
一趟快排的时间复杂度是O(n)。而多趟结果是O(nlogn)。快排被认为是数量级O(nlogn)的排序方法中,平均性能最好的。
快排也是不稳定的。
简单选择排序:
void Select_Sort(int a[])
{
inti,j,k,t;
for(i=0;i<10;i++)
{
k=i;
for(j=i;j<10;j++)
{
if(a[j]>a[i])//findindex of the max number
k=j;
}
t=a[k];
a[k]=a[i];
a[i]=t;
}
}
稳定性:不稳定
关键字比较次数为:n(n-1)/2,所以时间复杂度为O(n2),最好最坏都是O(n2)
直接插入排序:
注意这里设置了一个哨兵,0号元素。
所以数组的10元素编号是0~10
void InsertSort(int a[])
{
inti,j;
for(i=2;i<=10;i++)
if(a[i-1]>a[i])//只有当代插入元素小于已有序序列的最后一个元素是才需要进行记录移动
{
a[0]=a[i];
for(j=i-1;a[j]>a[0];j--)
a[j+1]=a[j];
a[j+1]=a[0];
}
}
稳定性:稳定。
当序列已经是正序时,不需要进行记录移动,只需要进行n-1次比较,所以,最好时间复杂度是O(n),当关键字逆序时,需要进行(n+2)(n-1)/2(即是)比较,还要进行(n+4)(n-1)/2(即是)次记录的移动。所以最差情况下时间复杂度是O(n2)。若待排序记录是随机的,即待排序的记录可能出现的各种排列的概率相同,则我们可取上述最小值和最大值的平均值,作为直接插入排序时的所需进行关键字间的比较次数和移动记录的次数,约为n2/4。由此,所以直接插入排序的平均时间复杂度为O(n2)
希尔排序:
一趟排序算法:
void SHELL_Sort(int a[],int dk)
{
inti,j;
for(i=dk+1;i<=10;i++)
{
if(a[i]<a[i-dk])
{
a[0]=a[i];
for(j=i-dk;j>0&&a[j]>a[0];j-=dk)
{
a[j+dk]=a[j];
}
a[j+dk]a[0];
}
}
}
希尔排序是不稳定的排序算法,dk的存在,可能使相同的元素分开排序导致结果不同。其时间复杂度和增量序列有关,涉及数学上的尚未解决的难题。
堆排序:
void HeapAdjust(int a[],int r,int n)//假设其他记录都已经调整为堆,进行一次调整,将第r个记录调整到位,n是元素个数
{
inti,key;
key=a[r];
for(i=r*2;i<=n;i*=2)
{
if(i<n&&a[i]>a[i+1])//如果i==n就不用++了,因为再加就越界了
i++;//找出两元素较小者
if(key<a[i])//key比左右孩子都小,不必继续调整
break;
a[i/2]=a[i];
r=i;
}
a[r]=key;
}
注意构成堆的条件是每个根节点都大于等于两个孩子节点(大顶堆)或者每个根节点都小于等于孩子节点(小顶堆)。
堆排序最好最坏情况的时间复杂度都是O(nlogn)