目錄
一、直接插入排序
二、希爾排序
三、直接選擇排序
四、堆排序
五、冒泡排序
六、快速排序
七、歸并排序
一、直接插入排序
思想:
? ? ? ? ? ? ?定義i下標(biāo)之前的元素全部已經(jīng)有序,遍歷一遍要排序的數(shù)組,把i下標(biāo)前的元素全部進(jìn)行排序,當(dāng)遍歷玩這個(gè)數(shù)組后,就已經(jīng)排好序了。
代碼如下:
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;
}
}
代碼解析
? ? ? ? ? ? ? ? 要使i下標(biāo)之前的元素都有序,定義一個(gè)j下標(biāo),為i - 1;再用tmp記錄i下標(biāo)的位置,只要j下標(biāo)元素比tmp大,j下標(biāo)的元素就要放到j(luò)+1下標(biāo),最后j走完后,再把最小的tmp放在j+1位置。
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
????????時(shí)間:O(n^2)
????????空間:O(1)
????????穩(wěn)定性:穩(wěn)定
二、希爾排序
思想:
? ? ? ? ? ? ? ? 希爾排序也稱縮小增量排序,就是分次去進(jìn)行排序,越排到后面就會(huì)越有序,每次間隔是gap,然后逐漸縮小,到最后間隔為0,也就是用我們的直接插入排序,數(shù)組越有序,速度也會(huì)越快。那么就很簡(jiǎn)單了,我們只需改一下直接插入排序每次排序的間隔,把他們分成不同組進(jìn)行排序,直到最后間隔為0,就只剩一組,然后也是用直接插入排序,做最后一次排序,排完就是有序的了。
圖式例:
代碼如下:
public static void shellSort(int[] array) {
int gap = array.length / 2;
while (gap >= 1) {
gap /= 2;
shell(array, gap);
}
}
public static void shell(int[] array, int gap) {
for (int i = gap; i < array.length; 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;
}
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
????????時(shí)間:n^1.3(嚴(yán)蔚敏) 因?yàn)間ap取值方式不同,計(jì)算出來(lái)的時(shí)間復(fù)雜度也會(huì)不同
? ? ? ? 空間:O(1)
? ? ? ? 穩(wěn)定性:不穩(wěn)定
三、直接選擇排序
思想:
? ? ? ? ? ? ? ? 直接選擇排序也是和直接插入排序差不多,定義i下標(biāo)前的元素全部都有序,不過(guò)排序的方式不同,它是拿i下標(biāo)前的元素和i下標(biāo)后的元素進(jìn)行比較,找到下標(biāo)最小的元素,把最小元素放進(jìn)i下標(biāo)中,同時(shí)這個(gè)i下標(biāo)元素放到被這個(gè)最小下標(biāo)位置。
代碼實(shí)現(xiàn):
public static void selectSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int minIndex = i;//記錄最小值的下標(biāo)
for (int j = i+1; j < array.length; j++) {
if(array[j] < array[minIndex]) {
minIndex = j;
}
}
//走完這里,找到最小元素的下標(biāo)minIndex
//交換
int tmp = array[i];
array[i] = array[minIndex];
array[minIndex] = tmp;
}
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
? ? ? ? 時(shí)間:O(n^2)
? ? ? ? 空間:O(1)
? ? ? ? 穩(wěn)定性:不穩(wěn)定
四、堆排序
思想:
? ? ? ? ? ? ? ? 堆其實(shí)就是完全二叉樹(shù),下標(biāo)是從上到下,從左到右依次遞增,要把堆排序成升序,就要把他先變成大根堆,每次出大根堆的頂點(diǎn),把頂點(diǎn)放在最后一個(gè)節(jié)點(diǎn),然后再向下調(diào)整一次,第二次把大根堆的頂點(diǎn)放到倒數(shù)第二個(gè)位置,依次往后推。
代碼實(shí)現(xiàn):
//堆排序
public static void heapSort(int[] array) {
//先轉(zhuǎn)換成大根堆
createHeap(array);
//開(kāi)始換,然后向下轉(zhuǎn)換
for (int i = array.length - 1; i > 0 ; i--) {
//i下標(biāo)的節(jié)點(diǎn)和堆頂交換
int tmp = array[0];
array[0] = array[i];
array[i] = tmp;
//向下調(diào)整
siftDown(array,0, i);
}
}
//創(chuàng)建大根堆
public static void createHeap(int[] array) {
//從最后一個(gè)父節(jié)點(diǎn)開(kāi)始向下調(diào)整,下標(biāo)依次往前減
//parent = (child - 1) / 2; 左:child = parent * 2 + 1 右:child = parent * 2 + 2
for (int i = (array.length - 1 - 1) / 2; i >= 0 ; i--) {
siftDown(array, i, array.length);
}
}
//向下調(diào)整
public static void siftDown(int[] array, int parent, int length) {
//定義一個(gè)child為該父節(jié)點(diǎn)的左孩子
int child = parent * 2 + 1;
while (child < length) {
//比較改父節(jié)點(diǎn)的左右孩子,把值最大的孩子作為交換節(jié)點(diǎn)
if(array[child] < array[child + 1]) {
child += 1;
}
//比較父節(jié)點(diǎn)和孩子節(jié)點(diǎn)大小
if(array[parent] < array[child]) {
//交換
int tmp = array[parent];
array[parent] = array[child];
array[child] = tmp;
parent = child;
child = child * 2 + 1;
} else {
break;
}
}
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
? ? ? ? 時(shí)間復(fù)雜度:O(NlogN)
? ? ? ? 空間復(fù)雜度:O(1)
? ? ? ? 穩(wěn)定性:不穩(wěn)定
五、冒泡排序
思想:
? ? ? ? ? ? ? ? 冒泡排序的思想很簡(jiǎn)單,就是第一次把最大的值放到數(shù)組最后一個(gè)下標(biāo)中,再把第二大的元素放到數(shù)組倒數(shù)第二個(gè)下標(biāo)中,依次類推
代碼實(shí)現(xiàn):
//冒泡排序
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length; i++) {
boolean flag = false;//標(biāo)記
for (int j = 0; j < array.length - 1 - i; j++) {
if(array[j] > array[j + 1]) {
//交換
int tmp =array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
flag = true;
}
}
if(!flag) {
break;
}
}
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
????????時(shí)間復(fù)雜度:O(N^2)
????????空間復(fù)雜度:O(1)
????????穩(wěn)定性:穩(wěn)定
六、快速排序
思想:
? ? ? ? ? ? ? ? 使用遞歸思想(也可以采用非遞歸思想),把一組數(shù)據(jù)劃分成兩部分,左邊都小于該下標(biāo)元素,右邊都大于該下標(biāo)元素,再在左邊去找元素劃分,右邊元素去劃分,依次往后推,直到左右兩邊都沒(méi)有元素可以劃分了,就是只剩一個(gè)元素了,這時(shí)候往回倒,就有序了
代碼實(shí)現(xiàn):
public static void quickSort(int[] array) {
int left = 0;
int right = array.length - 1;
quick(array, left, right);
}
public static void quick(int[] array, int start, int end) {
//遞歸結(jié)束條件
if(start >= end) {
return;
}
int pivot = partition(array, start, end);
quick(array, start, pivot - 1);
quick(array, pivot + 1, end);
}
public static int partition(int[] array, int left, int right) {
//找到一個(gè)下標(biāo)元素,左邊都比這個(gè)下標(biāo)元素小,右邊都比這個(gè)下標(biāo)元素大,并且還要返回這個(gè)下標(biāo)
//記錄下標(biāo)為0的值,放在tmp中
int tmp = array[0];
while (left < right) {
//先走右邊
while(left < right && array[right] >= tmp) {
right--;
}
while(left < right && array[left] <= tmp) {
left++;
}
//左下標(biāo)的值大于tmp,右下標(biāo)的值小于tmp,這兩個(gè)下標(biāo)值交換
int newTmp = array[left];
array[left] = array[right];
array[right] = newTmp;
}
//走到這,left和right相遇了,left下標(biāo)的值和tmp交換,并且返回這個(gè)位置的下標(biāo)
int newTmp = tmp;
tmp = array[left];
array[left] = newTmp;
return left;
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
????????時(shí)間復(fù)雜度:O(NlogN)
????????空間復(fù)雜度:O(logN~N)
????????穩(wěn)定性:不穩(wěn)定文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-714382.html
七、歸并排序
思想:
? ? ? ? ? ? ? ? 將一組數(shù)組分割成左右兩部分,和快速排序找出的中件位置不同,歸并的中間位置是最左和最右下標(biāo)相加再除2(left+right)/ 2,運(yùn)用的也是遞歸思想(也可以采用非遞歸思想),采用分治法,一直找到最左邊進(jìn)行排序,然后再找最右邊進(jìn)行排序,再往歸回整體排序(合并),合并的時(shí)候是放在一個(gè)臨時(shí)數(shù)組中,再把這個(gè)臨時(shí)數(shù)組拷貝到原數(shù)組,下標(biāo)要對(duì)應(yīng)
代碼實(shí)現(xiàn):
public static void mergeSort(int[] array) {
int start = 0;
int end = array.length - 1;
mergeSortFunc(array, start, end);
}
//套殼
public static void mergeSortFunc(int[] array, int start, int end) {
//遞歸結(jié)束標(biāo)志
if(start >= end) {
return;
}
//求出中間節(jié)點(diǎn)位置
int mid = (start + end) / 2;
//左邊
mergeSortFunc(array, start, mid);
//右邊
mergeSortFunc(array, mid + 1, end);
//合并
merge(array, start, mid, end);
}
//合并
public static void merge(int[] array, int left, int mid, int right) {
//定義mid兩邊的左右下標(biāo)
int s1 = left;
int e1 = mid;
int s2 = mid + 1;
int e2 = right;
//定義一個(gè)新的數(shù)組,存放array排序完后的數(shù)組
int[] tmpArray = new int[right - left - 1];
int k = 0;
while (s1 <= e1 && s2 <= e2) {
//比較左右兩邊s1和s2的值
if(array[s1] < array[s2]) {
tmpArray[k++] = array[s1++];
} else {
tmpArray[k++] = array[s2]++;
}
if(s1 <= e1) {
tmpArray[k++] = array[s1++];
}
if(s2 <= e2) {
tmpArray[k++] = array[s2++];
}
}
//拷貝到原數(shù)組
for (int i = 0; i < tmpArray.length; i++) {
array[left + i] = tmpArray[i];
}
}
時(shí)間復(fù)雜度、空間復(fù)雜度、穩(wěn)定性:
????????時(shí)間復(fù)雜度:O(NlogN)
????????空間復(fù)雜度:O(N)
????????穩(wěn)定性:不穩(wěn)定
都看到這了,給個(gè)免費(fèi)的贊唄,謝謝謝謝?。?!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-714382.html
到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu)中的七大排序(Java實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!