<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
當插入第i(i>=1)個元素時,前面的array[0],array[1],…,array[i-1]已經排好序,此時用array[i]與array[i-1],array[i-2],…進行比較,找到插入位置即將array[i]插入,原來位置上的元素順序後移。
資料越接近有序,直接插入排序的時間消耗越少。
時間複雜度:O(N^2)
空間複雜度O(1),是一種穩定的演演算法
直接插入排序:
public static void insertSort(int[] array){ for (int i = 1; i < array.length; i++) { int tmp=array[i]; int j=i-1; for(;j>=0;--j){ if(array[j]>tmp){ array[j+1]=array[j]; }else{ break; } } array[j+1]=tmp; } }
希爾排序法的基本思想是:先選定一個整數gap,把待排序檔案中所有記錄分成gap個組,所有距離為gap的數分在同一組內,並對每一組內的數進行直接插入排序。然後取gap=gap/2,重複上述分組和排序的工作。當gap=1時,所有數在一組內進行直接插入排序。
希爾排序 :
public static void shellSort(int[] array){ int size=array.length; //這裡定義gap的初始值為陣列長度的一半 int gap=size/2; while(gap>0){ //間隔為gap的直接插入排序 for (int i = gap; i < size; i++) { int tmp=array[i]; int j=i-gap; for(;j>=0;j-=gap){ if(array[j]>tmp){ array[j+gap]=array[j]; }else{ break; } } array[j+gap]=tmp; } gap/=2; } }
時間複雜度:O(N^2)
空間複雜度為O(1),不穩定
選擇排序 :
//交換 private static void swap(int[] array,int i,int j){ int tmp=array[i]; array[i]=array[j]; array[j]=tmp; } //選擇排序 public static void chooseSort(int[] array){ for (int i = 0; i < array.length; i++) { int minIndex=i;//記錄最小值的下標 for (int j = i+1; j < array.length; j++) { if (array[j]<array[minIndex]) { minIndex=j; } } swap(array,i,minIndex); } }
堆排序的兩種思路(以升序為例):
時間複雜度:O(N^2)
空間複雜度:O(N),不穩定
堆排序:
//向下調整 public static void shiftDown(int[] array,int parent,int len){ int child=parent*2+1; while(child<len){ if(child+1<len){ if(array[child+1]>array[child]){ child++; } } if(array[child]>array[parent]){ swap(array,child,parent); parent=child; child=parent*2+1; }else{ break; } } } //建立大根堆 private static void createHeap(int[] array){ for (int parent = (array.length-1-1)/2; parent >=0; parent--) { shiftDown(array,parent,array.length); } } //堆排序 public static void heapSort(int[] array){ //建立大根堆 createHeap(array); //排序 for (int i = array.length-1; i >0; i--) { swap(array,0,i); shiftDown(array,0,i); } }
兩層迴圈,第一層迴圈表示要排序的趟數,第二層迴圈表示每趟要比較的次數;這裡的氣泡排序做了優化,在每一趟比較時,我們可以定義一個計數器來記錄資料交換的次數,如果沒有交換,則表示資料已經有序,不需要再進行排序了。
時間複雜度:O(N^2)
空間複雜度為O(1),是一個穩定的排序
氣泡排序:
public static void bubbleSort(int[] array){ for(int i=0;i<array.length-1;++i){ int count=0; for (int j = 0; j < array.length-1-i; j++) { if(array[j]>array[j+1]){ swap(array,j,j+1); count++; } } if(count==0){ break; } } }
任取待排序元素序列中的某元素作為基準值,按照該排序碼將待排序集合分割成兩子序列,左子序列中所有元素均小於基準值,右子序列中所有元素均大於基準值,然後最左右子序列重複該過程,直到所有元素都排列在相應位置上為止。
時間複雜度:最好O(n*logn):每次可以儘量將待排序的序列均勻分割
最壞O(N^2):待排序序列本身是有序的
空間複雜度:最好O(logn)、 最壞O(N)。不穩定的排序
(1)挖坑法
當資料有序時,快速排序就相當於二元樹沒有左子樹或右子樹,此時空間複雜度會達到O(N),如果大量資料進行排序,可能會導致棧溢位。
public static void quickSort(int[] array,int left,int right){ if(left>=right){ return; } int l=left; int r=right; int tmp=array[l]; while(l<r){ while(array[r]>=tmp&&l<r){ //等號不能省略,如果省略,當序列中存在相同的值時,程式會死迴圈 r--; } array[l]=array[r]; while(array[l]<=tmp&&l<r){ l++; } array[r]=array[l]; } array[l]=tmp; quickSort(array,0,l-1); quickSort(array,l+1,right); }
(2)快速排序的優化
三數取中法選key
關於key值的選取,如果待排序序列是有序的,那麼我們選取第一個或最後一個作為key可能導致分割的左邊或右邊為空,這時快速排序的空間複雜度會比較大,容易造成棧溢位。那麼我們可以採用三數取中法來取消這種情況。找到序列的第一個,最後一個,以及中間的一個元素,以他們的中間值作為key值。
//key值的優化,只在快速排序中使用,則可以為private private int threeMid(int[] array,int left,int right){ int mid=(left+right)/2; if(array[left]>array[right]){ if(array[mid]>array[left]){ return left; } return array[mid]<array[right]?right:mid; }else{ if(array[mid]<array[left]){ return left; } return array[mid]>array[right]?right:mid; } }
遞迴到小的子區間時,可以考慮用插入排序
隨著我們遞迴的進行,區間會變的越來越小,我們可以在區間小到一個值的時候,對其進行插入排序,這樣程式碼的效率會提高很多。
(3)快速排序的非遞迴實現
//找到一次劃分的下標 public static int patition(int[] array,int left,int right){ int tmp=array[left]; while(left<right){ while(left<right&&array[right]>=tmp){ right--; } array[left]=array[right]; while(left<right&&array[left]<=tmp){ left++; } array[right]=array[left]; } array[left]=tmp; return left; } //快速排序的非遞迴 public static void quickSort2(int[] array){ Stack<Integer> stack=new Stack<>(); int left=0; int right=array.length-1; stack.push(left); stack.push(right); while(!stack.isEmpty()){ int r=stack.pop(); int l=stack.pop(); int p=patition(array,l,r); if(p-1>l){ stack.push(l); stack.push(p-1); } if(p+1<r){ stack.push(p+1); stack.push(r); } } }
歸併排序(MERGE-SORT):該演演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為二路歸併。
時間複雜度:O(n*logN)(無論有序還是無序)
空間複雜度:O(N)。是穩定的排序。
//歸併排序:遞迴 public static void mergeSort(int[] array,int left,int right){ if(left>=right){ return; } int mid=(left+right)/2; //遞迴分割 mergeSort(array,left,mid); mergeSort(array,mid+1,right); //合併 merge(array,left,right,mid); } //非遞迴 public static void mergeSort1(int[] array){ int gap=1; while(gap<array.length){ for (int i = 0; i < array.length; i+=2*gap) { int left=i; int mid=left+gap-1; if(mid>=array.length){ mid=array.length-1; } int right=left+2*gap-1; if(right>=array.length){ right=array.length-1; } merge(array,left,right,mid); } gap=gap*2; } } //合併:合併兩個有序陣列 public static void merge(int[] array,int left,int right,int mid){ int[] tmp=new int[right-left+1]; int k=0; int s1=left; int e1=mid; int s2=mid+1; int e2=right; while(s1<=e1&&s2<=e2){ if(array[s1]<=array[s2]){ tmp[k++]=array[s1++]; }else{ tmp[k++]=array[s2++]; } } while(s1<=e1){ tmp[k++]=array[s1++]; } while(s2<=e2){ tmp[k++]=array[s2++]; } for (int i = left; i <= right; i++) { array[i]=tmp[i-left]; } }
排序方法 | 最好時間複雜度 | 最壞時間複雜度 | 空間複雜度 | 穩定性 |
直接插入排序 | O(n) | O(n^2) | O(1) | 穩定 |
希爾排序 | O(n) | O(n^2) | O(1) | 不穩定 |
直接排序 | O(n^2) | O(n^2) | O(1) | 不穩定 |
堆排序 | O(nlog(2)n) | O(nlog(2)n) | O(1) | 不穩定 |
氣泡排序 | O(n) | O(n^2) | O(1) | 穩定 |
快速排序 | O(nlog(2)n) | O(n^2) | O(nlog(2)n) | 不穩定 |
歸併排序 | O(nlog(2)n) | O(nlog(2)n) | O(n) | 穩定 |
到此這篇關於Java 資料結構七大排序使用分析的文章就介紹到這了,更多相關Java 排序內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45