- 冒泡排序
冒泡排序很简单,将最大的数放在最后,或者将最小的数放在最前面即可。
最好情况比较次数为n-1,移动次数为0,最好情况下的时间复杂度为O(n)
最坏情况的时间复杂度为O(n^2 ) 平均时间复杂度为O(n^2)
代码
void bubble_sort(int num[],int n)
{
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(num[j]>num[j+1])
{
int tem=num[j];
num[j]=num[j+1];
num[j+1]=tem;
}
}
}
for(int i=0;i<n-1;i++)
{
for(int j=n-1;j>i;j--)
{
if(num[j]<num[j-1])
{
int tem = num[j];
num[j]=num[j-1];
num[j-1]=tem;
}
}
}
}
- 快速排序
快速排序一点要记住,快速排序是基于分治法的,每次选一个标兵,通过一趟的排序将待排序表划分为独立的两部分,是的标兵的坐标全是小于标兵的元素,标兵的右边全是大于标兵的元素。然后再以标兵的左边作为子表重新进行排序,标兵的右边作为子表重新进行排序,直到low=high
快速排序空间复杂度:快排是递归。需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量应与递归调用的最大深度一致,最好情况下为log2(n+1),最坏情况下进行n-1递归调用,站的深度为O(n),平均情况下栈的深度为O(log2n)
快排的时间复杂度:与划分是否对称有关,若初始排序表基本有序或者基本逆序时,最坏情况下的时间复杂度为O(n^2)。最理想的情况下,能做到均匀的划分,此时时间复杂度为O(nlog2n)。但快速排序平均情况下的运行时间与其最佳的运行时间很接近,而不是接近最坏情况下的运行时间
快速排序是一种不稳定的排序
这里有一个小题:如果是要取第k大的元素也可以利用快排,主要是利用partition函数,当标兵最后确定的位置,也就是low是k的时候,就可以结束并输出了,如果标兵的low小于了k,那么就在标兵的右边,则在quick_sort(num,mid+1,high)中进行继续查找,若标兵的low大于了k,那么就在标兵的左边,quick_sort(num,low,mid-1)中继续查找,直到找到为止
int partition(int num[],int low,int high)
{
int pkey = num[low];
while(low<high)
{
while(low<high&&pkey<=num[high])
{
high--;
}
num[low]=num[high];
while(low<high&&pkey>=num[low])
{
low++;
}
num[high]=num[low];
}
num[low]=pkey;
return low;
}
void quick_sort(int num[],int low,int high)
{
if(low<high)
{
int mid = partition(num,low,high);
quick_sort(num,low,mid-1);
quick_sort(num,mid+1,high);
}
}
- 简单选择排序
选择排序就是每次选最大或者最小的放在最后或者最前面
void select_sort(int num[],int n)
{
for(int i=0;i<n-1;i++)
{
int min = i;
for(int j=i+1;j<n;j++)
{
if(num[j]<num[min])
{
min = j;
}
}
int tem=num[i];
num[i]=num[min];
num[min]=tem;
}
}
- 堆排序
堆排序我这里只做了大顶堆,并且还不是很懂。都是我太笨了wwww
堆排序是一种完全二叉树的结构,n个关键字序列,num[i]<=num[i2],num[i]<=num[i2+1]为小顶堆,um[i]>=num[i2],num[i]>=num[i2+1]。
值得注意的是,堆最好从1开始,从0开始我不是很懂。
堆排序主要是先构造初始堆(大顶堆),构造初始堆的方法是从k=n/2开始到1,逐步向下调整,每次都找子节点中较大的那个开始筛选,如果比父节点要小,那么筛选结束,这个k没有可以调整的,如果比父节点要大,那么要需要交换父节点和子节点的位置,并将k该变为子节点的编号,继续向下筛选,并调整为大顶堆
初始堆的第一个元素是整个表中最大的元素,最终堆排序是每次将堆中的第一个元素与最后一个交换位置,然后调整从第一个元素到第n-1个元素调整堆为大顶堆,然后再取第一个元素和最后一个交换位置,这样调整n-1趟结束排序
空间复杂度 O(1)
时间复杂度建堆时间为O(n),之后有n-1次向下调整的操作,每次调整的操作时间复杂度为O(h),堆排序的时间复杂度为O(n*log2n)
堆排序是一种不稳定的排序方法
void adjustDown(int num[],int k,int n)
{
int tem = num[k];
for(int i=k*2;i<=n;i*=2)
{
if(i<n&&num[i]<num[i+1])
i++;
if(tem>=num[i])
break;
else
{
num[k]=num[i];
num[i]=tem;
k=i;
}
}
}
void build_max_heap(int num[],int n)
{
for(int i=n/2;i>0;i--)
{
adjustDown(num,i,n);
}
}
void heap_sort(int num[],int n)
{
build_max_heap(num,n);
for(int i=n;i>1;i--)
{
int tem=num[1];
num[1]=num[i];
num[i]=tem;
adjustDown(num,1,i-1);
}
}