Java常用的九種排序方法及程式碼實現
阿新 • • 發佈:2018-11-13
- package com.algorithm.Demo;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- public class SortRecoder {
- public static void main(String[] args) {
- SortRecoder SR = new SortRecoder();
- int[] a={49,38,65,97,76,13,27,49,78,34,12,64,5,4,18,23,34,15,35,25,53};
- System.out.println(" --1.直接插入排序--");
- SR.insertSort(a);
- System.out.println(" --2.希爾排序--");
- SR.sheelSort(a);
- System.out.println(" --3.簡單選擇排序--");
- SR.selectSort(a);
- System.out.println(" --4.堆排序--");
- SR.heapSort(a);
- System.out.println(" --5.氣泡排序--");
- SR.bubbleSort(a);
- System.out.println(" --6.快速排序--");
- SR.FastSort(a,0,a.length-1);
- SR.printAll(a);
- System.out.println(" --7.歸併排序--");
- SR.mergingSort(a,0,a.length-1);
- SR.printAll(a);
- System.out.println(" --8.基數排序--");
- SR.radixSort(a);
- System.out.println(" --9.類方法排序--");
- SR.ArraySort(a);
- }
- // 列印完整序列
- public void printAll(int[] list) {
- for (int value : list) {
- System.out.print(value+" ");
- }
- System.out.println();
- }
- //1.直接插入排序
- //將大於要插入值的數整體後移一個單位 ,將需要插入的小數值向前移一位。
- public void insertSort(int[] a){
- for(int i=1;i<a.length;i++){
- int insertNum=a[i];//要插入的數 38,65,97,76,13,27...
- int j=i-1;
- //依次比較更換位置
- for(;j>=0&&insertNum<a[j];j--){ //將大於要插入值的數整體後移一個單位 ,j減少1。
- a[j+1]=a[j];
- }
- a[j+1]=insertNum;//將需要插入的數放在要插入的位置。
- }
- this.printAll(a);
- }
- //2.希爾排序(最小增量排序) --對於直接插入排序問題,資料量巨大時。
- // 演算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,
- // 每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,
- // 在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。
- public void sheelSort(int[] a){
- int d = a.length;
- while (d!=0) {
- d=d/2;
- for (int x = 0; x < d; x++) {//分的組數
- for (int i = x + d; i < a.length; i += d) {//組中的元素,從第二個數開始
- int j = i - d;//j為有序序列最後一位的位數
- int temp = a[i];//要插入的元素
- for (; j >= 0 && temp < a[j]; j -= d) {
- a[j + d] = a[j];//向後移動d位
- }
- a[j + d] = temp;
- }
- }
- }
- this.printAll(a);
- }
- //3.簡單選擇排序 --常用於取序列中最大最小的幾個數時。
- //遍歷整個序列,將最小的數放在最前面。遍歷剩下的序列,將最小的數放在最前面。
- public void selectSort(int[] a) {
- int length = a.length;
- for (int i = 0; i < length; i++) {//迴圈次數
- int key = a[i];
- int position=i;
- for (int j = i + 1; j < length; j++) {//選出最小的值和位置
- if (a[j] < key) {
- key = a[j];
- position = j;
- }
- }
- a[position]=a[i];//交換位置
- a[i]=key;
- }
- this.printAll(a);
- }
- //4.堆排序 --是一種樹形選擇排序,是對直接選擇排序的有效改進。
- //將根節點與最後一個節點交換,然後斷開最後一個節點。重複第一、二步,直到所有節點斷開。根節點是最小值
- public void heapSort(int[] a){
- int arrayLength=a.length;
- //迴圈建堆
- for(int i=0;i<arrayLength-1;i++){
- //建堆
- buildMaxHeap(a,arrayLength-1-i);
- //交換堆頂和最後一個元素
- swap(a,0,arrayLength-1-i);
- //System.out.println(Arrays.toString(a));
- }
- this.printAll(a);
- }
- private void swap(int[] data, int i, int j) {
- int tmp=data[i];
- data[i]=data[j];
- data[j]=tmp;
- }
- //對data陣列從0到lastIndex建大頂堆
- private void buildMaxHeap(int[] data, int lastIndex) {
- //從lastIndex處節點(最後一個節點)的父節點開始
- for(int i=(lastIndex-1)/2;i>=0;i--){
- //k儲存正在判斷的節點
- int k=i;
- //如果當前k節點的子節點存在
- while(k*2+1<=lastIndex){
- //k節點的左子節點的索引
- int biggerIndex=2*k+1;
- //如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在
- if(biggerIndex<lastIndex){
- //若果右子節點的值較大
- if(data[biggerIndex]<data[biggerIndex+1]){
- //biggerIndex總是記錄較大子節點的索引
- biggerIndex++;
- }
- }
- //如果k節點的值小於其較大的子節點的值
- if(data[k]<data[biggerIndex]){
- //交換他們
- swap(data,k,biggerIndex);
- //將biggerIndex賦予k,開始while迴圈的下一次迴圈,重新保證k節點的值大於其左右子節點的值
- k=biggerIndex;
- }else{
- break;
- }
- }
- }
- }
- //5.氣泡排序
- //自上而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒
- public void bubbleSort(int[] a){
- int temp;
- for(int i=0;i<a.length;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;
- }
- }
- }
- this.printAll(a);
- }
- //6.快速排序 --要求時間最快時。
- //選擇第一個數為p,小於p的數放在左邊,大於p的數放在右邊。遞迴的將p左邊和右邊的數都按照第一步進行,直到不能遞迴
- public void FastSort(int[] a,int low,int high){
- int start = low;
- int end = high;
- int key = a[low];
- while(end>start){
- //從後往前比較
- while(end>start&&a[end]>=key) //如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置,然後又從前往後比較
- end--;
- if(a[end]<=key){
- int temp = a[end];
- a[end] = a[start];
- a[start] = temp;
- }
- //從前往後比較
- while(end>start&&a[start]<=key)//如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
- start++;
- if(a[start]>=key){
- int temp = a[start];
- a[start] = a[end];
- a[end] = temp;
- }
- //此時第一次迴圈比較結束,關鍵值的位置已經確定了。左邊的值都比關鍵值小,右邊的值都比關鍵值大,但是兩邊的順序還有可能是不一樣的,進行下面的遞迴呼叫
- }
- //遞迴
- if(start>low) FastSort(a,low,start-1);//左邊序列。第一個索引位置到關鍵值索引-1
- if(end<high) FastSort(a,end+1,high);//右邊序列。從關鍵值索引+1到最後一個
- }
- //7.歸併排序 --速度僅次於快排
- //選擇相鄰兩個陣列成一個有序序列。 然後再把相鄰有序子序列合併為整體有序序列。重複執行,直到全部組成一個有序序列
- public void mergingSort(int[] data, int left, int right) {
- if(left<right){
- //找出中間索引
- int center=(left+right)/2;
- //對左邊陣列進行遞迴
- mergingSort(data,left,center);
- //對右邊陣列進行遞迴
- mergingSort(data,center+1,right);
- //合併
- merge(data,left,center,right);
- }
- }
- public void merge(int[] data, int left, int center, int right) {
- int [] tmpArr=new int[data.length];
- int mid=center+1;
- //third記錄中間陣列的索引
- int third=left;
- int tmp=left;
- while(left<=center&&mid<=right){
- //從兩個陣列中取出最小的放入中間陣列
- if(data[left]<=data[mid]){
- tmpArr[third++]=data[left++];
- }else{
- tmpArr[third++]=data[mid++];
- }
- }
- //剩餘部分依次放入中間陣列
- while(mid<=right){
- tmpArr[third++]=data[mid++];
- }
- while(left<=center){
- tmpArr[third++]=data[left++];
- }
- //將中間陣列中的內容複製回原陣列
- while(tmp<=right){
- data[tmp]=tmpArr[tmp++];
- }
- //System.out.println(Arrays.toString(data));
- }
- //8.基數排序 --用於大量數,很長的數進行排序時。
- //將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。
- public void radixSort (int[] array) {
- //首先確定排序的趟數;
- int max = array[0];
- for (int i = 1; i < array.length; i++) {
- if (array[i] > max) {
- max = array[i];
- }
- }
- int time = 0;
- //判斷位數;
- while (max > 0) {
- max /= 10;
- time++;
- }
- //建立10個佇列;
- List<ArrayList> queue = new ArrayList<ArrayList>();
- for (int i = 0; i < 10; i++) {
- ArrayList<Integer> queue1 = new ArrayList<Integer>();
- queue.add(queue1);
- }
- //進行time次分配和收集;
- for (int i = 0; i < time; i++) {
- //分配陣列元素;
- for (int j = 0; j < array.length; j++) {
- //得到數字的第time+1位數;
- int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
- ArrayList<Integer> queue2 = queue.get(x);
- queue2.add(array[j]);
- queue.set(x, queue2);
- }
- int count = 0;//元素計數器;
- //收集佇列元素;
- for (int k = 0; k < 10; k++) {
- while (queue.get(k).size() > 0) {
- ArrayList<Integer> queue3 = queue.get(k);
- array[count] = queue3.get(0);
- queue3.remove(0);
- count++;
- }
- }
- }
- this.printAll(array);
- }
- //9.類方法降序排列
- public void ArraySort(int[] a){
- Arrays.sort(a);
- //this.printAll(a);
- for(int i=0,j=a.length-1;i<j;i++,j--){
- int temp=a[i];
- a[i]=a[j];
- a[j]=temp;
- }
- this.printAll(a);
- }
- }