简单的三种排序
总结:排序算法中最基本的三种算法(简单选择,冒泡,插入),这三种排序算法的时间复杂度均为O(n2)
性能总结:
1、稳定性:归并排序最好。
2、空间复杂度:堆排序最好。
3、经过优化的快速排序最好,普通快速排序像是情绪化的天才。
引出原因:
1、归并排序:堆排序结构复杂,直接利用完全二叉树。1.分解:将当前区间一分为二,即求分裂点2.求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;3.组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。
2、堆排序:简单选择排序,在待排的n个记录中选择一个最小的记录,需要比较n-1次。但是这样的操作没有把每一趟比较结果保存下来。堆排序:在每次选择最小记录同时,根据比较结果对其他记录做出调整。
3、快速排序:和冒泡类似,需要不断比较和交换实现排序。但是快排增大了比较和移动的距离,从而减少总的交换次数。
复杂度分析:
1、归并排序:时间复杂度计算:O(nlogn):对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。空间复杂度:归并过程需要记录,占用内存但稳定
2、堆排序:运行时间主要消耗在初始构建堆和重建堆时反复筛选上。
1)初始构建堆:从最下层最右边非叶节点开始,并对左右孩子进行比较、交换。O(n)
2)重建堆:每一次取堆顶记录并重建需要O(logN),完全二叉树深度为|logN|+1。,需要取n-1次循环,O(NlogN)
3、快速排序:
时间复杂度取决于二叉树的深度。
最优:平衡二叉树。深度log2N+1,需要递归log2N次,第一次对整个数组扫描做n次比较,复杂度O(n*logn)
最差:正序或逆序,斜二叉树,每次划分只比上一次划分少一个记录,复杂度O(n2)
空间复杂度:递归造成栈空间使用。
最好:递归树深度为log2N,复杂度为O(logN)
最差:需要n-1次递归,复杂度为O(n)
冒泡算法
冒泡排序的基本思想是,对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。
时间复杂度为O(n2)
void bubbleSort(int arr[],int n){//冒泡排序
int flag=true;
for(int i=0;i<n-1;i++){
flag=false;
for(int j=n-1;j>=i;j--){//j是从底向上循环,冒泡
if(arr[j]<arr[j-1]){//下面的小了,要交换
swap(arr,j,j-1);
flag=true;
}
}
if(flag==false)
break;设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已然完成。
}
}
冒泡优化进程:
第一版:
for(int i=1;i<n;i++)
for( int j=i+1;j<n;j++)
if(arr[i]>arr[j])//从上到下
swap();
第二版:
for(int i=0;i<n-1;i++){
for(int j=n-1;j>=i;j--){//j是从底向上循环,冒泡
if(arr[j]<arr[j-1]){//下面的小了,要交换
swap(arr,j,j-1);
第三版:
加flag 避免重复无用比较
简单选择算法
基本思想:当前后面n-i次比较中选出最小的记录,