以下代碼均整理自互聯網。
快排:// 見筆記本 10頁快排的思路
public class Code_04_QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
public static void quickSort(int[] arr, int l, int r) {
if (l < r) {
//隨機選一個位置的數與最後位置交換,形成隨機快排。
// l + (int) (Math.random() * (r - l + 1)) 表示在l和r之間隨機選一個數
swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
//不要上一行就是經典快排
int[] p = partition(arr, l, r); //partiton劃分的意思,這個是荷蘭國旗問題
quickSort(arr, l, p[0]);
quickSort(arr, p[1], r);
//進來一組數據,分成左邊一坨小於它,右邊一坨大於它,然後對左邊一坨,中間等於的一坨
//左邊分出的一坨又重新這樣做(因爲同樣的問題,所以調用自己),右邊分出來的一坨也這樣做,
// 所以遞歸多了後面那兩個quikSort
//後面再本程序開頭加上遞歸終止條件即可。歸併排序也是這樣的,只不過後面多了歸併的部分。
}
}
public static int[] partition(int[] arr, int l, int r) {
int less = l - 1;
int more = r;//因爲是用最後一個數作爲基準數的,所以這裏是r,後面記得把這個基準數
// 放到中間相等的部分,且more是中間相等部分的上一個數,自己可以找兩個數想一想。
while (l < more) { //因爲l有時候找到比他大的數是不走的,所以只能用while。
if (arr[l] < arr[r]) { //l後續不會交換,所以用來做遍歷下標
swap(arr, ++less, l++); //這裏一定要小心
} else if (arr[l] > arr[r]) {
swap(arr, --more, l);//這裏一定要小心,l是不動的
} else {
l++;
}
}
swap(arr, more, r); //最後一位還是與中間相等的數,所以要交換到中間去。
//more就是相等數的最後一位,但是less是中間相等數的前一位,下一步返回邊界要小心
return new int[] { less, more+1 }; //返回中間相等的上下邊界,返回回去後面直接對左右部分同樣處理。
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String [] args) {
System.out.println("hello");
int [] arr = new int [] {5,6,8,31,2};
quikSort(arr,0,arr.length-1);
for (int i = 0; i<arr.length; i++) {
System.out.print(arr[i]);
System.out.print(" ");
}
}
}
插入排序:筆記本第4頁
public class insertSort {
public static void insertSort(int[] arr) {
if(arr.length<2||arr==null) return ;
for(int i = 1; i<arr.length; i++) {
for(int j = i-1; j>-1 && arr[j+1]<arr[j]; j--)//關鍵的地方在於這兒
// 核心思路和打牌一樣,當前元素和前一個比,小就交換,交換後還要比較,所以j和j+1比,這裏是關鍵
swap(arr,j+1,j);
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] p = new int [] {1,5,9,3,66,8,4,3};
insertSort(p);
for(int i = 0; i<p.length;i++) {
System.out.print(p[i]);
System.out.print(" ");
}
}
}
歸併排序:筆記本第6頁
import java.util.Arrays;
public class mergeSort {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
mergeSort(arr, 0, arr.length - 1);
}
public static void mergeSort(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = l + ((r - l) >> 1);//l,r中點的位置,這樣寫是爲了防止溢出。
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r); //左右兩邊排好序
merge(arr, l, mid, r); //對進來的數組進行前後半部分進行重組
// 這一步必須寫在最後,因爲從底部開始合併,然後合併上一步,即對數組的兩半部分進行類似樹的後續遍歷一樣
// 這樣做的原因是,本層進行合併的時候,在merge前是要保證左半部分和右半部分是排好序的,所以是後續遍歷
// 這一步也是劍指offer有道題是將兩個排序好的鏈表合併爲一個鏈表。
// 和剛剛快排很類似,進來一個數組,切成左邊一組,右邊一組,只要還可以切,
// 就繼續切(所以有了後兩步mergesort),直到不能切返回,後面多了merge步驟。
}
public static void merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];//如{3,2,4},l是0,r是2進來,長度是2-0+1=3,所以長度要分好
int i = 0;
int p1 = l;
int p2 = m + 1; //用兩個指針去掃描數組的前後部分
while (p1 <= m && p2 <= r) {
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 下面兩個循環表示誰走完後,另一個數組直接複製後面的內容。
while (p1 <= m) {
// 這裏和下面的循環自己寫的時候沒寫等號,錯了想了很久。因爲上面截止後,還會自加,所以會超出原邊界,依次作爲判斷條件。
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
// 複製回去
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i]; //一定注意下標要對應原始數組的下標
}
}
public static void main(String[] args) {
int[] p = new int [] {1,5,9,3,66,8,4,3};
mergeSort(p);
for(int i = 0; i<p.length;i++) {
System.out.print(p[i]);
System.out.print(" ");
}
}
}
冒泡排序:
public class maopao {
public static void bubbleSort(int[] arr) {
if(arr==null||arr.length<2) return ;
for(int i = 0; i<arr.length;i++) {
//每一趟將最大的數放到最後,且下一趟會比上一趟少一個數比較(其實最後一趟沒有必要,因爲就他一個人)
for(int j = 0;j<arr.length-1-i;j++) {
if (arr[j]>arr[j+1])
swap(arr,j+1,j);
}
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] p = new int [] {1,5,9,3,66,8,4,3};
bubbleSort(p);//bubble冒泡
for(int i = 0; i<p.length;i++) {
System.out.print(p[i]);
System.out.print(" ");
}
}
}
選擇排序:
import java.util.Arrays;
public class Code_02_SelectionSort {
public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) { //因爲j=i+1
int minIndex = i;
// 從0位置開始,每一趟找一個最小的數,放在該趟對應的下標處
for (int j = i + 1; j < arr.length; j++) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
//記錄最小位置的下標,這樣減少交換次數。
}
swap(arr, i, minIndex); //這一趟走完,才把這一趟對應位置的數換成後半部分最小的數。
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] p = new int [] {1,5,9,3,66,8,4,3};
selectionSort(p);//bubble冒泡
for(int i = 0; i<p.length;i++) {
System.out.print(p[i]);
System.out.print(" ");
}
}
}
堆排序:筆記本11頁
import java.util.Arrays;
public class Code_03_HeapSort {
// 將數組排序轉換爲二叉樹形式,然後通過大根堆調整得到數組的排序
public static void heapSort(int[] arr) {
//第一步判斷數組
if (arr == null || arr.length < 2) {
return;
}
//第二步建立大根堆:heapInsert
// 遍歷每一個節點,如果比父節點大,則交換--->建立大根堆
for (int i = 0; i < arr.length; i++) {
heapInsert(arr, i);
}
// 第三步:大根堆只保證父比子大,無法保證左右,所以通過不斷的讓父節點去堆尾節點,然後調整實現排序
int size = arr.length;
swap(arr, 0, --size); //頭尾交換 (不可以和while合併寫循環第一條?)
while (size > 0) {
heapify(arr, 0, size); //調 大根堆
swap(arr, 0, --size); // 頭尾交換,並尾部往前移
}
}
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) { //若比父節點大則交換,(index - 1) / 2當前節點的父節點
// 和插入一樣,交換後也許還是大,所以要一直交換,知道不用交換爲止
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
// 每次將大根堆放到尾部後,頭結點是比較小的,然後頭結點和子節點的交換,一直交換到上一步最尾部的上一個數
public static void heapify(int[] arr, int index, int size) {
int left = index * 2 + 1;
while (left < size) { //看是否越界在葉子節點上
// left + 1 就是右孩子,下一句是右孩子不越界,且三目運算返回最大孩子的下標
// 若右節點越界則返回左結點的值(即沒有右節點)
int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
// 這一句是我和孩子誰大(上一步找到最大的孩子下標),誰大下標給largest
largest = arr[largest] > arr[index] ? largest : index;
// if條件表示,節點變小後但仍然比孩子都大,則不用往下沉
if (largest == index) {
break;
}
swap(arr, largest, index);
index = largest; //頭結點變大後,交換的節點還要繼續往下沉,讓頭結點=index
left = index * 2 + 1;
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] p = new int [] {1,5,9,3,66,8,4,3};
heapSort(p);//bubble冒泡
for(int i = 0; i<p.length;i++) {
System.out.print(p[i]);
System.out.print(" ");
}
}
面試常考的常用數據結構與算法:https://blog.csdn.net/zwj1030711290/article/details/70224852
https://www.cnblogs.com/onepixel/articles/7674659.html 排序算法這個上面總結的很好。
排序算法的一點點應用-海量數據處理,這個總結的好:
https://blog.csdn.net/v_JULY_v/article/details/7382693