【Java資料結構與演算法筆記(一)】常見排序演算法及面試考點總結
一切為了暑期實習,一切為了暑期實習。
我就是試著去面面,實習是不可能實習的,老闆是不會讓我們去的。
哭!!!
以下是正題!!!
2019年3月11日:突然想做成一個整理筆記了,那這個就作為開篇吧~
以下排序排名有先後之分,請注意複習策略~
快速排序
快排特別重要!!!
快排特別重要!!!
快排特別重要!!!
基本思想
- 首先在陣列中選擇一個基準點(一般選取第一個數字),
- 然後分別從陣列的兩端掃描陣列,設兩個指示標誌(low指向起始位置,high指向末尾),
( 首先從後半部分開始,如果發現有元素比該基準點的值小,就交換low和high位置的值,然後從前半部分開始掃秒,發現有元素大於基準點的值,就交換low和high位置的值,如此往復迴圈,直到low>=high,然後把基準點的值放到high這個位置。一次排序就完成了。) - 以後採用遞迴的方式分別對前半部分和後半部分排序,當前半部分和後半部分均有序時該陣列就自然有序了。
程式碼實現
package algorithm;
public class QuickSort {
public static void main(String[] args) {
int[] arr={49,38,65,97};
int low = 0, high = arr.length-1;
quickSort(arr,low,high);
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
public static void quickSort(int[] arr, int low, int high) {
if(low >= high) return;
int index = partition(arr,low,high);
quickSort(arr,low,index-1);
quickSort(arr,index+1,high);
}
public static int partition(int[] arr, int low, int high) {
int key = arr[low];
while(low < high) {
while(low < high && arr[high] >= key) high --;
arr[low] = arr[high];
while(low < high && arr[low] <= key) low ++;
arr[high] = arr[low];
}
arr[high] = key;
return high;
}
}
快排的改進思路
詳細的看這裡:https://blog.csdn.net/hacker00011000/article/details/52176100
我看有的面經上有問到這個,趕緊總結下:
(回答的時候別給自己挖坑,選自己能實現的回答)
- 優化1:當待排序序列的長度分割到一定大小後,使用插入排序;
- 優化2:在一次分割結束後,可以把與Key相等的元素聚在一起,繼續下次分割時,不用再對與key相等元素分割;
- 優化3:使用尾遞迴優化遞迴操作;
- 優化4:使用並行或多執行緒處理子序列。
氣泡排序
基本思想
相鄰兩節點進行比較,大的向後移一個,經過第一輪兩兩比較和移動,最大的元素移動到了最後,第二輪次大的位於倒數第二個,依次進行。
程式碼實現
package algorithm;
public class BubbleSort {
public static void main(String[] args) {
int[] arr={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
bubbleSort(arr);
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
public static void bubbleSort(int[] arr) {
for(int i=0;i<arr.length-1;i++) {
for(int j=0;j<arr.length-1-i;j++) {
if(arr[j]>arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
直接插入排序
基本思想
遍歷陣列,遍歷到i時,a0,a1…ai-1是已經排好序的,取出ai,從ai-1開始向前和每個比較大小,如果小於,則將此位置元素向後移動,繼續先前比較,如果不小於,則放到正在比較的元素之後。可見相等元素比較是,原來靠後的還是拍在後邊,所以插入排序是穩定的。
程式碼實現
package algorithm;
public class InsertSort {
public static void main(String[] args) {
int[] arr={49,38,65,97,76,13,27,49,78};
insertSort(arr);
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
public static void insertSort(int[] arr) {
for(int i=1;i<arr.length;i++) {
int temp = arr[i];
int j=i-1;
while(j>=0 && arr[j]>temp) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
}
}
歸併排序
基本思想
首先考慮下如何將將二個有序數列合併。這個非常簡單,只要從比較二個數列的第一個數,誰小就先取誰,取了後就在對應數列中刪除這個數。然後再進行比較,如果有數列為空,那直接將另一個數列的資料依次取出即可。
程式碼實現
package algorithm;
public class MergeSort {
public static void main(String[] args) {
int[] arr={49,38,65,97,38};
int low = 0, high = arr.length-1;
mergeSort(arr,low,high);
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
public static void mergeSort(int[] arr, int low, int high) {
if(low < high) {
int mid = (low+high)/2;
mergeSort(arr,low,mid);
mergeSort(arr,mid+1,high);
merge(arr,low,mid,high);
}
}
public static void merge(int[] arr, int low, int mid, int high) {
int[] temp = new int[high-low+1];
int k=0,i=low,j=mid+1;
while(i<=mid && j<=high) {
if(arr[i]<arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
while(i<=mid)
temp[k++] = arr[i++];
while(j<=high)
temp[k++] = arr[j++];
for(k=0;k<temp.length;k++) {
arr[low+k] = temp[k];
}
}
}
簡單選擇排序
package algorithm;
public class SelectSort {
public static void main(String[] args) {
int[] arr={4,1,3,7};
selectSort(arr);
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
public static void selectSort(int[] arr) {
for(int i=0;i<arr.length;i++) {
int index=i;
for(int j=i+1;j<arr.length;j++)
if(arr[index]>arr[j])
index = j;
int temp = arr[index];
arr[index] = arr[i];
arr[i] = temp;
}
}
}
各種排序演算法比較(table)
問題1: 穩定性
- 什麼是排序演算法的穩定性(摘自百度百科)
假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序後的序列中,r[i]仍在r[j]之前,則稱這種排序演算法是穩定的;否則稱為不穩定的。
- 對於不穩定的排序演算法,只要舉出反例,即可說明它的不穩定性;而對於穩定的排序演算法,必須對演算法進行分析從而得到穩定的特性。
- 快(快排)些(希爾)選(簡單選擇)一堆(堆排序)這四個都是不穩定的,可以按照
快些選一堆
快些選一堆
快些選一堆
這個順口溜記,我覺得還是很方便的,考驗之後兩年多了,都沒忘!!
問題2: 空間複雜度
兩種演算法需要特殊記:
- 快排:由於需要一個輔助棧來實現遞迴,空間複雜度平均為
O(log2n)
,最壞情況下為O(n)
- 歸併排序:在合併操作中需要藉助較多的輔助空間用於元素複製,所以為
O(n)
- 其他演算法都為
O(1)
問題3: 時間複雜度
大部分參照上面的table即可,但是需要特別注意快排,我在四場面試問到過兩次
- 平均時間複雜度為
O(nlog2n)
,但是在元素基本有序的時候反而效能最低為O(n)
- 快排被認定為目前內部排序效能最好的演算法
以上,差不多可以應付面試了,如果有問題及時反饋給我哦~
相關文章
- 演算法、資料結構 常見面試題演算法資料結構面試題
- Java資料結構與排序演算法 (一)Java資料結構排序演算法
- 常見排序演算法總結排序演算法
- 【演算法與資料結構】經典排序演算法總結演算法資料結構排序
- 資料結構與演算法整理總結---排序 2資料結構演算法排序
- 資料結構與演算法知識點總結(4)各類排序演算法資料結構演算法排序
- 資料結構與演算法----# 一、排序資料結構演算法排序
- Java資料結構與排序演算法 (三)Java資料結構排序演算法
- Java資料結構與排序演算法 (二)Java資料結構排序演算法
- 常見Java面試知識點總結Java面試
- 資料結構與演算法常見問題(面試題)不定時更新資料結構演算法面試題
- 幾種常見排序演算法總結排序演算法
- 資料結構與演算法——排序資料結構演算法排序
- PMP 考試常見工具與技術點總結
- [資料結構與演算法] 排序演算法資料結構演算法排序
- 幾種常見的排序演算法總結排序演算法
- 資料結構和演算法面試題系列—排序演算法之快速排序資料結構演算法面試題排序
- 【PHP資料結構】PHP資料結構及演算法總結PHP資料結構演算法
- [資料結構拾遺]字串排序演算法總結資料結構字串排序演算法
- 資料結構與演算法——排序演算法-歸併排序資料結構演算法排序
- 資料結構與演算法——排序演算法-基數排序資料結構演算法排序
- 資料結構與演算法——排序演算法-氣泡排序資料結構演算法排序
- 資料結構與演算法——排序演算法-選擇排序資料結構演算法排序
- 資料結構與演算法(八):排序資料結構演算法排序
- 資料結構與演算法之排序資料結構演算法排序
- 資料結構與演算法:堆排序資料結構演算法排序
- 【資料結構與演算法】堆排序資料結構演算法排序
- 資料結構與演算法——堆排序資料結構演算法排序
- 資料庫常見面試題總結資料庫面試題
- 資料結構和演算法面試題系列—排序演算法之基礎排序資料結構演算法面試題排序
- Java集合類常見面試知識點總結Java面試
- 資料結構和演算法面試題系列—遞迴演算法總結資料結構演算法面試題遞迴
- 資料結構和演算法面試題系列—隨機演算法總結資料結構演算法面試題隨機
- 大資料面試常見的面試題總結大資料面試題
- C++連結串列常見面試考點C++面試
- 資料結構與演算法——十個排序演算法資料結構演算法排序
- 資料結構與演算法(java)資料結構演算法Java
- 資料結構與演算法 排序與搜尋資料結構演算法排序