排序算法
Posted 刘宛秋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法相关的知识,希望对你有一定的参考价值。
最近看了《大话数据结构》简单的把上面的算法总结一下:
简单算法:冒泡排序,简单选择排序,直接插入排序
改进算法:希尔排序,堆排序,归并排序,快速排序
插入排序:直接插入排序和希尔排序
交换排序:冒泡排序和快速排序
选择排序:简单选择排序和堆排序
冒泡排序:
思想:两两比较相邻记录的关键字,大的放后面。这样,每一轮下来,最大的被放在了最后。
Java代码: public int[] sort(int[] a){ int temp = 0; for (int i = a.length - 1; i > 0; --i){ for (int j = 0; j < i; ++j){ if (a[j + 1] < a[j]){ temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } return a; }
简单选择排序:
简单选择排序性能上略优于冒泡排序:
简单选择排序是从第一个元素开始(i=0),依次与其后的元素进行比较,找出最小元素的下标(j),放在下标是i的位置。
Java代码为: public int[] selectsort(int[] array){ int min,temp;//最小数标记 int len = array.Length; for(int i=0; i<len; i++){ min=i; for(int j=i+1; j<len; j++){ if(array[min]>array[j]){ min=j; } } tmp=array[i]; array[i]=array[min]; array[min]=tmp; } return array; }
直接插入排序:
直接插入排序是将一个记录插入到已经排好序的有序表中。
第一个元素不管了,相当于直接放进去的,然后后面的元素依次与前面的元素进行比较。所以下标是从1开始的。
Java代码如下: private int[] insertSort(int[] arr){ if(arr == null || arr.length < 2){ return arr; } for(int i=1;i<arr.length;i++){ for(int j=i;j>0;j--){ if(arr[j]<arr[j-1]){ int temp=arr[j]; arr[j]=arr[j-1]; arr[j-1]=temp; }else{ //接下来是无用功 break; } } } return arr; }
希尔排序:
希尔排序是插入排序的一种
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。
public int[] ShellSort(int[] a){ int len=a.length; while(true){ len=len/2; for(int x=0;x<len;x++){ for(int i=x+len;i<a.length;i=i+len){ int temp=a[i]; int j; for(j=i-len;j>=0 && a[j]>temp;j=j-len){ //此for循环实现排序,差不多相当于插入排序 //与其前元素比较,当前元素比比较的元素小,其它元素后移 //给当前元素让位置 a[j+len]=a[j]; } //此元素比它前面的元素大,把空出来的位置放此元素 a[j+len]=temp; } } if(len==1){ break; } } return a; }
快速排序:
关键字靠近谁,保护谁(原理自己百度一下吧,死记),每一轮选出一个关键字,两个指针low和high,先选数组中的第一个元素作为关键字
public void sort(int arr[],int low,int high){ int l=low; int h=high; int povit=arr[low]; while(l<h){ while(l<h&&arr[h]>=povit) h--; if(l<h){ int temp=arr[h]; arr[h]=arr[l]; arr[l]=temp; l++; } while(l<h&&arr[l]<=povit){ l++; } if(l<h){ int temp=arr[h]; arr[h]=arr[l]; arr[l]=temp; h--; } } if(l>low) sort(arr,low,l-1); if(h<high) sort(arr,l+1,high); return arr; }
堆排序:
大顶堆:从最后一个非叶子节点开始,往前逐步调整,让每个双亲都大于子女,至到根结点为止。每次找到最大结点后放置最后一个位置。然后再调整出最大的放在倒数第二个位置。
创建堆的时候就一个一个元素向二叉树上添加,不用管排序情况。序列表中前一半的程序就是此二叉树的非叶子节点。
//堆排序 public class HeapSort { public static void main(String[] args) { int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3 }; heapSort(array); } public static void heapSort(int[] array) { if (array == null || array.length <= 1) { return; } buildMaxHeap(array); for (int i = array.length - 1; i >= 1; i--) { exchangeElements(array, 0, i); maxHeap(array, i, 0); } } private static void buildMaxHeap(int[] array) { if (array == null || array.length <= 1) { return; } //[0...half]是非叶子节点 int half = array.length / 2; for (int i = half; i >= 0; i--) { //把当前树的数组,数组长度,子树根的位置传过去 maxHeap(array, array.length, i); } } private static void maxHeap(int[] array, int heapSize, int index) { int left = index * 2 + 1; int right = index * 2 + 2; //树根的位置记录下来 int largest = index; //左子树存在并且左子树值比根大 if (left < heapSize && array[left] > array[index]) { //标记出大的位置 largest = left; } //右子树存在,并且右子树的值比之前找出的最大的值大 if (right < heapSize && array[right] > array[largest]) { largest = right; } if (index != largest) { //跟下标和找出的最大值下标不一样,交换这两个值 exchangeElements(array, index, largest); //替换后元素的堆,让它重新平衡 maxHeap(array, heapSize, largest); } } //交换两个元素的值 public static void exchangeElements(int[] array, int index1, int index2) { int temp = array[index1]; array[index1] = array[index2]; array[index2] = temp; } }
以上是关于排序算法的主要内容,如果未能解决你的问题,请参考以下文章