常见排序算法
来源:互联网 发布:ubuntu root 登录 编辑:程序博客网 时间:2024/06/07 17:20
复习了几种常见排序算法,整理起来以加强印象。
按稳定性的不同分为:
稳定排序:插入排序,冒泡排序,归并排序,基数排序。
不稳定排序:选择排序,快速排序,希尔排序,堆排序。
1.冒泡排序
思想:每一轮排序都把最大或最小的元素往后调,如果有n个元素,则一共会进行n-1轮排序,每一轮排序会比较n-1-i次。
时间复杂度:O(N*N)
相等元素的前后顺序在排序过程中不会改变,是稳定排序。
代码:
void bubblesort(int a[],int n){ int i,j;for(i=0;i<n-1;i++){for(j=0;j<n-1-i;j++){int temp;if(a[j]>a[j+1]){temp=a[j];a[j]=a[j+1];a[j+1]=temp;}}}}
2.选择排序
思想:第一轮排序在所有元素中选出最大或最小的元素放在第一位,第二轮排序在剩下的元素中选出最大或最小的元素放在第二位,以此类推。
时间复杂度:O(N*N)
相等元素的前后顺序在排序过程中会改变,是不稳定排序。
代码:
void select_sort(int a[],int n){ int i,j; int minindex;//这里是按升序排列 int temp; for(i=0;i<n-1;i++) { minindex=i; for(j=i+1;j<n;j++) { if(a[minindex]>a[j]) { minindex=j; } } temp=a[i]; a[i]=a[minindex]; a[minindex]=temp; }}
3.插入排序
思想:假设第一位是排好序的,从第二位元素开始,第i轮排序把第i个元素插入到前i-1位已排好序的元素中(即从第i-1位元素开始往前比较, 直到找到自己的位置)。
时间复杂度:O(N*N)
相等元素的前后顺序在排序过程中不会改变,是稳定排序。
代码:
void insert_sort(int a[],int n){ int key; int i,j; for(i=1;i<n;i++) { key = a[i]; //默认前i-1个元素是排好序的,现在要将a[i]插入前i-1个元素中,使前i个元素是排好序的 if(key<a[i-1])//如果第i个元素比第i-1个元素大,就肯定比i-1个元素之前的元素都大 { for(j=i-1;j>=0&&a[j]>key;--j) { a[j+1]=a[j];//把大于key的元素都后移一位 } a[j+1] = key; } }}
思想:将第一个元素设置成枢纽元t,挖出来(挖坑法),此时第一个元素为空,设置i,j两个标记,i初始指向第一个元素,j初始指向最后一个元素。
当i<j时,反复以下循环过程:
1.将j向右移动,直到遇到一个小于t的数,将此数挖出并填到上一个坑(即挖第一个枢纽元t所产生的坑,i往右移一步),此时j指向的元素为空。
2.将i往左移,直到遇到一个大于t的数,将此数挖出并填到上一个坑(即上次挖坑后j指向的空位置,j往左移一步),此时i指向的元素为空。
当i等于j时,跳出循环,并把t填到i指向的坑中,这时,元素t的左边全都小于等于t,右边全都大于等于t。继续分别将左边和右边元素进行快排(分治思想)。
时间复杂度:最理想是O(N*logN),最差是O(N*N)
相等元素的前后顺序在排序过程中会改变(容易发生在枢纽元最后归位的时候),是不稳定排序。
代码:
void quicksort(int a[],int r,int l){int i=r;int j=l;int temp = a[r];if(i<j){while(i<j){ while(a[j]>=temp&&i<j)j--; if(i<j)a[i++]=a[j]; while(temp>=a[i]&&i<j)i++; if(i<j)a[j--]=a[i];}a[i]=temp;quicksort(a,r,i-1);quicksort(a,i+1,l);}}5.归并排序
思想:采用分治思想,首先递归将数组进行二分操作,分到不可再分的程度(即每一个分组都包含一个元素),然而将相邻的分组进行有序合并(递归回来),最后得到的数组即是排好序的。
时间复杂度:最理想、平均和最差都是是O(N*logN)
相等元素的前后顺序在排序过程中不会改变,是稳定排序。
代码:
合并分组:
void merge(int a[],int first,int mid,int last,int temp[]){ int i=first,j=mid+1; int k=0; while(i<=mid&&j<=last){ if(a[i]<=a[j]){ temp[k++] = a[i++]; } else{ temp[k++] = a[j++]; } } while(i<=mid){ temp[k++]=a[i++]; } while(j<=last){ temp[k++]=a[j++]; } for(int v=0;v<k;v++){ a[first+v] = temp[v]; }}进行归并排序:
void mergesort(int a[],int first,int last,int temp[]){ if(first < last) { int mid = (first + last) / 2; mergesort(a, first, mid, temp); //左边有序 mergesort(a, mid + 1, last, temp); //右边有序 merge(a, first, mid, last, temp); //再将二个有序数列合并 }}
6.希尔排序
思想:属于插入排序的一种,又称缩小增量排序。对于一个长度为n的待排序数列,取一个小于n的整数gap(增量)将整个数列分为若干子数列,数列中所有距离为gap的数分在同一个子数列中。然后对每一个子数列进行插入排序,一趟排序过后,该子数列变成了有序的。逐步减少gap的值,直到gap=1时,即所有数字被放到一个子数列中进行插入排序,最后得到的数列是有序的。
时间复杂度:希尔排序的时间复杂度与选取的增量有关,若增量为1,希尔排序则退化成直接插入排序,时间复杂度为O(N*N),若采用Hibbard序列2^k-1,时间复杂度为O(N^1.5)。
相等元素的前后顺序在排序过程中会改变,是不稳定排序。
代码:
void shellsort(int a[], int n) //n为元素个数{ for(int gap=n/2;gap>0;gap/=2){for (int j = gap; j < n; j++) {//从数组的第gap个元素开始if(a[j] < a[j - gap]) {//同一组内进行插入排序int temp = a[j];int k = j - gap;while (k >= 0 && a[k] > temp) {a[k + gap] = a[k];k -= gap;}a[k + gap] = temp;}} }}
7.堆排序
思想:构造数组对应的最小堆或最大堆(从非叶子结点开始进行下滤操作),删除堆的第0个数据,用最后一个结点填充,再进行下滤操作。最后输出数组即是排好序的。小根堆为降序,大根堆为升序。
时间复杂度:由于每次重新恢复堆的时间复杂度为O(logN),共N - 1次重新恢复堆操作,再加上前面建立堆时N / 2次向下调整,每次调整时间复杂度也为O(logN)。二次操作时间相加还是O(N * logN)。故堆排序的时间复杂度平均和最坏都为O(N*logN)。
相等元素的前后顺序在排序过程中会改变,是不稳定排序。
代码:
下滤操作:
void minHeapFixdown(int a[],int i,int n){ int temp = a[i]; int j = 2*i+1; while(j<n){ if(j+1<n&&a[j+1]<a[j])j++; if(a[j]>=temp)break; a[i]=a[j]; i=j; j=2*i+1; } a[i] = temp;}构造小根堆:
void makeMinHeap(int a[],int n){ for(int i=n/2-1;i>=0;i--){ minHeapFixdown(a,i,n); }}实例:
int main(){ int a[10]={456,23,12,3,1,0,5,7,-1,324}; int i; int n=10; makeMinHeap(a,10); for(i=n-1;i>=1;i--){ swapnum(a[0],a[i]); minHeapFixdown(a,0,i); } for(int i=0;i<n;i++){ cout<<a[i]<<" "<<endl; } return 0;}其中swapnum函数:
void swapnum(int &a,int &b){ a = a^b; b = a^b; a = a^b;}
- 常见的排序算法
- 常见排序算法
- 常见排序算法代码
- 常见排序算法
- 常见排序算法总结
- 常见排序算法
- 常见排序算法学习
- 常见排序算法总结
- 常见的排序算法
- 常见排序算法分析
- 常见排序算法总结
- 常见排序算法
- 常见排序算法
- 常见排序算法介绍
- 常见排序算法小结
- 常见排序算法总结
- 常见经典排序算法
- 常见排序算法
- 小记 字符串内插($)与String.Format 编译后效果一样
- ROS入门_1.11 使用 rqt_console 和 roslaunch
- 母猪为什么会起飞,答案我找到了
- Struts1实现文件上传
- 这几天要做美团页面的项目了。
- 常见排序算法
- 欢迎使用CSDN-markdown编辑器
- android增量更新----------------最简实现
- 【uml】动态图之活动图、状态图
- JZOJ 3823【NOIP2014模拟9.9】遇见
- ant基础学习
- php compact函数
- dockerUI 的安装以及使用
- 图论(四)宽度优先搜索BFS