排序算法
排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。根据排序过程中涉及的存储器不同,可以将排序算法分为内部排序,外部排序。在排序算法中,通常涉及两种操作,一比较关键字大小,二是移动。下面主要讨论下内部排序的几种常见算法。
一 冒泡排序
- 冒泡排序的过程是首先将第一个记录的关键字和第二个记录的关键字比较,如果两个关键字逆序L.r[1].key > L.r[2].key.交换位置。然后依次类推。直到n-1 和 n 和记录比较。上面的过程称为第一趟排序,结果是Key 值最大的记录项放到最后
- 然后进行第二趟排序。第二趟排序是从第1个记录项到第n-1个。第i趟排序是从第一个到第n-i个。
- 判断排序完成的标记是在第i趟排序中没有发生记录位置的改变。这样每趟排序比较了最多n-1 次,一共进行了n次。算法时间复杂度为O(n*n).在排序的过程中,从竖直方向上看,最小的像气泡一样的浮出来,最大的像石块一样沉入水底。因此称之为冒泡排序。
Java 代码实现整形数组排序。
static void BubbleSort(int args[]){
int len = args.length;
for (int j = 0; j < len; j++) {
for (int i = 0; i < len - j - 1; i++) {
System.out.println(i);
if (args[i] > args[i + 1]) {
int temp = args[i];
args[i] = args[i + 1];
args[i + 1] = temp;
}
}
}
for(int k = 0; k < len; k++){
System.out.print(args[k] + " ");
}
System.out.println();
}
根据排序完成的条件,如果排序已经完成,不再循环。优化的排序
static void BubbleSort(int args[]){
int len = args.length;
boolean change = false;
for (int j = 0; j < len - 1; j++) {
change = false;
for (int i = 0; i < len - j - 1; i++) {
System.out.println(i);
if (args[i] > args[i + 1]) {
int temp = args[i];
args[i] = args[i + 1];
args[i + 1] = temp;
change = true;
}
}
if(change == false)
break;
}
for(int k = 0; k < len; k++){
System.out.print(args[k] + " ");
}
System.out.println();
}
二 快速排序
1.选择一个基准元素,通常选择第一个元素
2.通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3. 然后分别对这两部分记录用同样的方法继续进行排序,直到剩余一个子序列无法排序。
static int parpation(int[] array, int l, int h){
int temp = array[l];
while(l < h){
while (l < h && array[h] >= temp)
h--;
array[l] = array[h];
array[h] = temp;
while(l < h && array[l] <= temp)
l++;
array[h] = array[l];
array[l] = temp;
}
return l;
}
static void quickSort(int [] array, int l, int h){
if (l < h) {
int cursor = parpation(array, l, h);
quickSort(array, l, cursor - 1);
quickSort(array, cursor + 1, h);
}
for (int k = l; k < h - l + 1; k++) {
System.out.print(array[k] + " ");
}
System.out.println();
}
三 直接插入插入排序
- 插入排序是将一个记录插入到前面已经排好的有序序列中。
- 第一步首先第一个记录为一个有序序列。从第二个元素开始,将第二个元素插入到前面的序列中。
- 第i元素 首先比较下 第i个记录和第i-1个记录的大小,i-1 < i。不用交换,如果i-1 > i ,则将i 插入到前面的有序队列中.插入操作首先临时记录第i个元素temp,同时记录j=i,然后第j-1个元素大于temp,j-1 后移, 否则插入。时间复杂度O(n*n)
static void insertionSort(int[] array){
int len = array.length;
for(int i = 1; i < len; i++){
if(array[i-1] > array[i]){
int j = i;
int temp = array[i];
for(j = i;j > 0 && array[j-1] > temp; j--){
array[j] = array[j-1];
}
array[j] = temp;
}
}
for(int k = 0; k < array.length; k++){
System.out.print(array[k] + " ");
}
System.out.println();
}
四 希尔排序
整体思想是:在直接插入排序的时候如果序列为有序的,那么一次插入排序循环即可完成排序,时间复杂度为:O(n),也就是说如果序列的混乱度比较低,那么直接排序可以大大提高性能;直接插入排序在n比较小的时候,效率也比较高。因此希尔排序是 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
- 选择一个增量序列t1,t2,…,tk,其中ti>t(i-1),tk=1;需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。。
- 每趟排序,根据对应的增量因子ti,将待排序列分割成若干长度为ti 的子序列,分别对各子序列进行直接插入排序。仅增量因子为1 时,整个序列作为一个序列来处理,直接插入排序一次完成排序。
- 根据增量因子做循环
static void shellInsert(int[] array, int dl){
for(int i = dl; i < array.length; i++){
if(array[i - dl] > array[i]){
int j = 0;
int temp = array[i];
for(j = i; j - dl >= 0 && array[j-dl] > temp; j -= dl){
array[j] = array[j-dl];
}
array[j] = temp;
}
}
}
static void shellSort(int[] array, int[]dl){
for(int i = 0; i < dl.length; i ++){
shellInsert(array, dl[i]);
}
for (int k = 0; k < array.length; k++) {
System.out.print(array[k] + " ");
}
System.out.println();
}
五 简单选择排序
选择排序的基本思想是:每一趟在后边n-i+1 的个记录中选出最小的元素,和n-i+1 的第一个元素交换。算法复杂度为O(n*n)
public static void selectionSort(int[] array) {
for(int i = 0; i < array.length - 1; i++) {
int min = i;
for(int j = i + 1; j < array.length; j++) {
if(array[j] < array[min]) {
min = j;
}
}
if(min != i) {
int temp = array[min];
array[min] = array[i];
array[i] = temp;
}
}
for(int k = 0; k < array.length; k++){
System.out.print(array[k] + " ");
}
System.out.println();
}
六 堆排序
堆的原理就是完全二叉树。设计到两个问题:
1. 如何将无序序列建成堆;
2. 输出堆顶元素后,怎样调整剩余n-1 个元素,使其成为一个新堆。
无序序列建堆采用渗透法反复渗透,在完全二叉树中,最后一个有子节点的节点为 n/2。
首先在这个节点建堆,然后依次向上渗透。
输出堆顶元素后,就是把堆顶元素和刚调整的堆的最后一个元素交换,这样最大的元素在栈顶,进行依次渗透排序即可。
static void headAdjust(int[] array, int node, int len){
int temp = array[node];
for(int j = 2*node+1 ; j < len; j = j*2 +1){
if( j + 1 < len && array[j] < array[j+1]) j++;
if(array[node] > array[j]) break;
array[node] = array[j];
array[j] = temp;
node = j;
}
}
static void heapSort(int[] array){
int len = array.length;
for(int i = (len -1) / 2; i >= 0; i-- ){
headAdjust(array, i, len);
}
for(int i = len -1; i > 0; i--){
int temp = array[0];
array[0] = array[i];
array[i] = temp;
headAdjust(array, 0, i);
}
for (int k = 0; k < array.length; k++) {
System.out.print(array[k] + " ");
}
System.out.println();
}