各种基本排序算法总结
2015-12-20 00:20
246 查看
虽然我们用的语言中有排序的函数,我们用的时候直接调用就可以,不过这些经典排序算法中的许多思想以及实现它们过程中的一些编程技巧在我们实际编程中还是被频繁被用到的,作为一个程序员,这是基本功,还是很有必要掌握的。
下面算法全部最终按从小到大排序。
1.冒泡排序
思想:相邻两个数进行比较,如果前一个更大,就和后一个交换,这样每次将未排序部分的最大的数添加到已排好序的部分的第一个,进行n-1次即可。
代码如下:
平均时间复杂度O(N^2),最坏O(N^2),最好O(N),辅助存储O(1),是稳定的排序算法。
2.选择排序
思想:每次将未排好序的部分的最小的数添加到已排好序的部分的末尾。
代码如下:
平均时间复杂度O(N^2),最坏O(N^2),最好O(N^2),辅助存储O(1),不稳定(看下 2,2,1就知道了,开始在前面的2,排好序后到后面去了)。
3.直接插入排序
思想:直接插入排序的思想是每次将未排序部分的第一个数插入到已排好序的部分,并使已排好序的部分依旧有序。
代码如下:
平均时间复杂度O(N^2),最坏O(N^2),最好O(N),辅助存储O(1),是稳定的排序算法。
4.快速排序
思想:把比某个数(一般取序列的第一个元素)小的数移到它的左边,大的数移到右边,分治递归这个过程,到序列只剩一个数自然就排好了。。
代码如下:
可以稍微简化下:
时间复杂度O(N*lg(N)),最坏O(N^2),最好O(N*lg(N)),辅助存储O(lg(N)),不稳定。
5.归并排序
思想:先一层层的往下【递推】到每个区间只有一个数,然后在【回归】的时候不断合并【区间内已经有序的区间】,并保证合并后的区间有序。
速度仅次于快速排序,一般用于总体无序,但是各子项相对有序的数列。
平均时间复杂度O(N*lg(N)),最坏O(N*lg(N)),最好O(N*lg(N)),稳定,辅助存储O(N)。
下次接着写。。。
下面算法全部最终按从小到大排序。
1.冒泡排序
思想:相邻两个数进行比较,如果前一个更大,就和后一个交换,这样每次将未排序部分的最大的数添加到已排好序的部分的第一个,进行n-1次即可。
代码如下:
public int[] mp(int[] a) { if (a == null || a.length == 0) { return null; } int temp; for (int i = 0; i < a.length - 1; i++) { for (int j = 0; j < a.length - i - 1; j++) { if (a[j] > a[j + 1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } return a; }
平均时间复杂度O(N^2),最坏O(N^2),最好O(N),辅助存储O(1),是稳定的排序算法。
2.选择排序
思想:每次将未排好序的部分的最小的数添加到已排好序的部分的末尾。
代码如下:
public int[] selectionSort(int[] a) { if (a == null || a.length == 0) { return null; } int k,temp; for(int i = 0;i < a.length - 1;i++) { k = i; for(int j = i+1;j < a.length;j++) { if(a[j] < a[k]) { k = j; } } if(k != i) { temp = a[i]; a[i] = a[k]; a[k] = temp; } } return a; }
平均时间复杂度O(N^2),最坏O(N^2),最好O(N^2),辅助存储O(1),不稳定(看下 2,2,1就知道了,开始在前面的2,排好序后到后面去了)。
3.直接插入排序
思想:直接插入排序的思想是每次将未排序部分的第一个数插入到已排好序的部分,并使已排好序的部分依旧有序。
代码如下:
public int[] insertionSort(int[] a) { if(a == null || a.length == 0) { return null; } int j,temp; for(int i = 1;i < a.length;i++) { temp = a[i];//a[i]会被a[j+1] = a[j]覆盖掉,所以先用一个变量存起来 j = i-1; while(j >= 0 && a[j] > temp) { a[j+1] = a[j]; j--; } a[j+1] = temp; } return a; }
平均时间复杂度O(N^2),最坏O(N^2),最好O(N),辅助存储O(1),是稳定的排序算法。
4.快速排序
思想:把比某个数(一般取序列的第一个元素)小的数移到它的左边,大的数移到右边,分治递归这个过程,到序列只剩一个数自然就排好了。。
代码如下:
void quickSort(int[] a,int low,int high) { if (low >= high) {//不要用low == high,下面i-1会小于low的 return; } int i = low,j = high,temp = a[low]; while (i < j) { while (i < j && a[j] >= temp) { j--; } if (i < j) { a[i++] = a[j]; } while (i < j && a[i] <= temp) { i++; } if (i < j) { a[j--] = a[i]; } } a[i] = temp; quickSort(a, low, i - 1); quickSort(a, i + 1, high); }
可以稍微简化下:
void quickSort(int[] a,int low,int high) { if (low >= high) { return; } int i = low,j = high; int temp = a[low]; while (i < j) { while (i < j && a[j] >= temp) { j--; } if (i < j) { a[i++] = a[j]; } while (i < j && a[i] <= temp) { i++; } a[j--] = a[i]; } a[i] = temp; quickSort(a, low, i - 1); quickSort(a, i + 1,high); }
时间复杂度O(N*lg(N)),最坏O(N^2),最好O(N*lg(N)),辅助存储O(lg(N)),不稳定。
5.归并排序
思想:先一层层的往下【递推】到每个区间只有一个数,然后在【回归】的时候不断合并【区间内已经有序的区间】,并保证合并后的区间有序。
#include<stdio.h> void merge(int a[],int s,int mid,int e,int temp[]) { int i = s,j = mid + 1,k = 0; while(i <= mid && j <= e) { if(a[i] <= a[j]) { temp[k++] = a[i++]; } else { temp[k++] = a[j++]; } } while(i <= mid) { temp[k++] = a[i++]; } while(j <= e) { temp[k++] = a[j++]; } for(int i = 0;i < k;i++) { a[s + i] = temp[i]; } } void mergeSort(int a[],int s,int e,int temp[]) { if(s < e) { mergeSort(a,s,(s + e) / 2,temp); mergeSort(a,(s + e) / 2 + 1,e,temp); merge(a,s,(s + e) / 2,e,temp); } } int main() { int a[] = {4,2,7,9,1,3,10,5}; int temp[8]; mergeSort(a,0,7,temp); for(int i = 0;i < 8;i++) { printf("%d ",a[i]); } free(temp); }
速度仅次于快速排序,一般用于总体无序,但是各子项相对有序的数列。
平均时间复杂度O(N*lg(N)),最坏O(N*lg(N)),最好O(N*lg(N)),稳定,辅助存储O(N)。
下次接着写。。。
相关文章推荐
- iOS Default-568@2x.png启动图片设置问题
- 【Swift】通过tag删除动态创建的UIButton
- HTML 排版与标签(一)
- 接口的作用(C#)
- 第五次Scrum meeting
- preg_match_all()匹配
- EF6:编写你自己的code first 数据迁移操作(睡前来一篇,翻译的)
- java递归方法
- ssh 10个选项
- 不用也要知道的几种算法(PHP版本)
- CocoaPod的安装及与Swift的桥接
- 第一次冲刺
- Towards Crazyswarms
- Palindrome Linked List
- 剑指offer系列之六十一:二叉树搜索树的第k个节点
- iOS新建项目架构规范
- Android Studio使用lambda
- 【转载】c#如何创建和使用socket链接池
- 类再生
- 抽象类和接口