java排序算法

来源:互联网 发布:mac pro 13.3屏幕尺寸 编辑:程序博客网 时间:2024/06/05 05:21
本文罗列java中的各种排序算法思想和编程实现。
java排序算法常用的有:快速排序、冒泡排序、选择排序、插入排序、堆排序、希尔排序、合并排序。

1. 快速排序

/* * 快速排序思想:采用经典的分治思想 * 1、通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小  * 2、然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列 */public class QuikSort {public static void main(String[] args) {int arr[]=new int[]{3,5,3,11,0,44,2,9,4,8,1};quikSort(arr,0,arr.length-1);print(arr);}public static void quikSort(int[] arr,int left,int right){//递归if(right>left){int middle=apart(arr,left,right);quikSort(arr,left,middle-1);quikSort(arr,middle+1,right);}}//一趟快速排序public static int apart(int[] arr,int left,int right){//key值取为左边第一个元素int key=arr[left];while(left<right){//从右边开始,找第一个小于key值的元素while(arr[right]>=key)right--;arr[left]=arr[right];//从左边开始,找第一个大于key值的元素while(right>left&&arr[left]<=key)left++;arr[right]=arr[left];}//此时left==rightarr[left]=key;return left;}public static void print(int[] arr){for(int i=0;i<arr.length;i++){if(i==arr.length-1)System.out.println(arr[i]);elseSystem.out.print(arr[i]+",");}}}

2. 冒泡排序和选择排序

/* * 冒泡排序和选择排序 * 冒泡排序思想:相邻的两个元素进行比较,如果符合条件换位 * 选择排序思想:将数组序列划分为无序和有序区,寻找无序区中的最小值和无序区的首元素交换,有序区扩大一个,循环最终完成全部排序 */public class BubbleSort {public static void main(String[] args) {int arr[]=new int[]{3,5,3,11,0,44,2,9,4,8,1};System.out.println("原数组:");print(arr);System.out.println("冒泡排序后:");bubbleSort(arr);print(arr);System.out.println("选择排序后:");bubbleSort(arr);print(arr);}//冒泡排序public static void bubbleSort(int[] arr){for(int x=0; x<arr.length-1; x++){for(int y=0; y<arr.length-1-x; y++){if(arr[y]>arr[y+1]){swap(arr,y,y+1);}}}}//选择排序public static void selectSort(int[] arr){for(int x=0; x<arr.length-1; x++){for(int y=x+1; y<arr.length; y++){if(arr[x]>arr[y]){swap(arr,x,y);}}}}//选择排序,记录每趟排序的最大值/最小值位置,只将最值与无序区的第1个元素进行交换public static void selectSort_2(int[] arr){for(int x=0; x<arr.length-1; x++){int num = arr[x];int index = x;for(int y=x+1; y<arr.length; y++){if(num>arr[y]){num = arr[y];index = y;}}if(index!=x)swap(arr,x,index);}}public static void swap(int[] arr,int i,int j){int temp  = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void print(int[] arr){for(int i=0;i<arr.length;i++){if(i==arr.length-1)System.out.println(arr[i]);elseSystem.out.print(arr[i]+",");}}}
3. 插入排序

/* * 插入排序 * 思想:把n个待排序的元素看成一个有序表和一个无序表。开始时有序表中只包含一个元素,无序表中包含n-1个元素。 * 排序过程中,每次从无序表中取出一个元素,把它的值和有序表中的元素的值进行比较,之后将其插入到有序表中适当的位置, * 使这个有序表成为一个新的有序表。 */public class InsertSort {public static void main(String[] args) {int arr[]=new int[]{3,5,3,11,0,44,2,9,4,8,1};System.out.println("排序前:");print(arr);insertSort(arr);System.out.println("排序后:");print(arr);}public static void insertSort(int[] arr){//待排序元素是除arr[0]之外的所有元素for(int i=1; i<arr.length; i++){          int insertVal = arr[i];          int index = i-1;          //搜索insetVal的插入位置,插入位置之后的元素需要顺延移动位置          while(index>=0 && insertVal<arr[index]){             arr[index+1] = arr[index];             index--;          }          arr[index+1] = insertVal;    }}public static void print(int[] arr){for(int i=0;i<arr.length;i++){if(i==arr.length-1)System.out.println(arr[i]);elseSystem.out.print(arr[i]+",");}}}
4. 堆排序

/* * 堆排序 * 个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质): * ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),当然,这是小根堆,大根堆则换成>=号。 * k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点。 *  * 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。 * 用大根堆排序的基本思想: * 1.先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 * 2.再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key * 3.由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。 * 4.直到无序区只有一个元素为止。 *  * 特点 * 堆排序(HeapSort)是一树形选择排序。堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构, * 利用完全二叉树中双亲结点和孩子结点之间的内在关系(参见二叉树的顺序存储结构),在当前无序区中选择关键字最大(或最小)的记录。 * 区别 * 直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录, * 又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过, * 但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。 * 堆排序可通过树形结构保存部分比较结果,可减少比较次数。 */public class HeapSort{private static int[]sort=new int[]{1,0,10,20,3,5,6,4,9,8,12,17,34,11};public static void main(String[] args){buildMaxHeapify(sort);heapSort(sort);print(sort);} private static void buildMaxHeapify(int[]data){//没有子节点的才需要创建最大堆,从最后一个的父节点开始int startIndex=getParentIndex(data.length-1);//从尾端开始创建最大堆,每次都是正确的堆for(int i=startIndex;i>=0;i--){maxHeapify(data,data.length,i);}} /***创建最大堆*heapSize需要创建最大堆的大小,一般在sort的时候用到,因为最多值放在末尾,末尾就不再归入最大堆了*index当前需要创建最大堆的位置*/private static void maxHeapify(int[] data,int heapSize,int index){//当前点与左右子节点比较int left=getChildLeftIndex(index);int right=getChildRightIndex(index); int largest=index;if(left<heapSize&&data[index]<data[left]){largest=left;}if(right<heapSize&&data[largest]<data[right]){largest=right;}//得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整if(largest!=index){int temp=data[index];data[index]=data[largest];data[largest]=temp;maxHeapify(data,heapSize,largest);}} /***排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的*/private static void heapSort(int[]data){//末尾与头交换,交换后调整最大堆for(int i=data.length-1;i>0;i--){int temp=data[0];data[0]=data[i];data[i]=temp;maxHeapify(data,i,0);}} /***父节点位置*/private static int getParentIndex(int current){return(current-1)>>1;} /***左子节点position注意括号,加法优先级更高*/private static int getChildLeftIndex(int current){return(current<<1)+1;} /***右子节点position*/private static int getChildRightIndex(int current){return(current<<1)+2;} private static void print(int[]data){int pre=-2;for(int i=0;i<data.length;i++){if(pre<(int)getLog(i+1)){pre=(int)getLog(i+1);System.out.println();}System.out.print(data[i]+"|");}} /***以2为底的对数*/private static double getLog(double param){return Math.log(param)/Math.log(2);}}
5. 希尔排序
/* * 希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。 * 该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。 * 思想: * 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。 * 先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1), * 即所有记录放在同一组中进行直接插入排序为止。 */public class ShellSort {public static void main(String[] args){int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1};System.out.println("排序之前:");for(int i=0;i<a.length;i++){System.out.print(a[i]+",");}//希尔排序int d=a.length;while(true){d=d/2;for(int x=0;x<d;x++){for(int i=x+d;i<a.length;i=i+d){int temp=a[i];int j;for(j=i-d;j>=0&&a[j]>temp;j=j-d){a[j+d]=a[j];        }a[j+d]=temp;}    }if(d==1){break;}}System.out.println();System.out.println("排序之后:");for(int i=0;i<a.length;i++){System.out.print(a[i]+",");}}}
6. 合并排序
/* * 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列, * 再把有序的子序列合并为整体有序序列。--分治思想 * 归并操作的工作原理如下: * 第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 * 第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置 * 第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 * 重复步骤3直到某一指针超出序列尾 * 将另一序列剩下的所有元素直接复制到合并序列尾 */public class MergeSort{/* * 二路归并 * 原理:将两个有序表合并和一个有序表 * s:第一个有序表的起始下标 * m:第二个有序表的起始下标 * t:第二个有序表的结束小标 */private static void merge(int[] a,int s,int m,int t){int[] tmp=new int[t-s+1];int i=s,j=m,k=0;while(i<m&&j<=t){if(a[i]<=a[j]){tmp[k]=a[i];k++;i++;}else{tmp[k]=a[j];j++;k++;    }    }while(i<m){tmp[k]=a[i];i++;k++;}while(j<=t){tmp[k]=a[j];j++;k++;}System.arraycopy(tmp,0,a,s,tmp.length);} /* * 每次归并的有序集合的长度 */public static void mergeSort(int[] a,int s, int len){int size=a.length;int mid=size/(len<<1);int c=size&((len<<1)-1);// -------归并到只剩一个有序集合的时候结束算法-------//if(mid==0)return;// ------进行一趟归并排序-------//for(int i=0;i<mid;++i){s=i*2*len;merge(a,s,s+len,(len<<1)+s-1);}// -------将剩下的数和倒数一个有序集合归并-------//if(c!=0)merge(a,size-c-2*len,size-c,size-1);// -------递归执行下一趟归并排序------//mergeSort(a,0,2*len);} public static void main(String[] args){ int[] a=new  int[]{4,3,6,1,2,5};mergeSort(a,0,1); for(int i=0;i<a.length;++i){System.out.print(a[i]+" ");}} }




0 0
原创粉丝点击