插入排序
/**
* 插入排序
* 感覺下面的寫法和冒泡排序類似
* 時間複雜度:
* 最壞:O(n2)
* 最好:O(n)
* 平均:O(n2)
*/
package others;
public class insertSort {
//所謂插入排序,其實就是類似於我們玩紙牌的時候的排序方法,每抽一張牌,都在前面已經排好序的牌中找一個合適的位置插入
public static int[] sort(int[] array){
//先判斷數組是否符合規定,也就是長度
if (array.length == 0 || array.length < 2){
return array;
}else {
//採用兩次for循環
//i指向當前元素的位置,由於0前面沒有任何元素,因此我們從下標爲1的地方開始
for (int i = 1; i < array.length; i++){
//此處for循環用來查找元素i要插入的位置
//用temp來臨時保存當前的元素值
int temp = array[i];
int j =i-1;
//此處j>=0應當放在array[j]>temp的前面
//&&具有截斷性,所以就不會導致j=-1時的array會報的錯誤了
while(j>=0&&array[j]>temp){
array[j+1]=array[j];
j--;
}
array[j+1]=temp;
}
}
return array;
}
public static void main(String[] args){
int array[] = {10,11,4,2,23,46,33,1};
array = insertSort.sort(array);
for (int num : array){
System.out.println(num);
}
}
}
歸併排序
/***
*
* 歸併排序
* 已完成
**/
package others;
public class mergeSort {
//給定一個數組和對應區域的起始和終止位置
public static void merge(int[] array,int start,int end){
//首先先判斷起始地址是否小於終止地址,是的話執行,否則跳過,用來處理
if (start < end){
//獲取要處理區間的中心mid
int mid = (start + end) / 2 ;
//遞歸調用merge處理index左邊
merge(array,start,mid) ;
//遞歸調用merge處理index右邊
merge(array,mid + 1,end) ;
//最後調用sort方法對此區間進行排序
sort(array,start,mid,end) ;
}
}
//其實這裏纔是歸併排序的重點,
public static void sort(int[] nums, int low, int mid, int high) {
//創建一個和給定區間想用長度的新的int空間
int[] temp = new int[high - low + 1];
int i = low;// 左指針
int j = mid + 1;// 右指針
int k = 0;
// 把較小的數先移到新數組中
//此處是將兩個有序的數組合併到一個新的數組中
//將兩個數組i和j位置處的元素進行比較,將較小的數放入到新數組中,對應的i或者j+1,直到有一方數組遍歷完
while (i <= mid && j <= high) {
if (nums[i] < nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
//由於我們不知道哪個數組是遍歷完的那一個,所以我們對兩個數組執行同樣的操作
//也就是把各自數組剩餘的所有元素一次性放到新數組的後方
//由於有一方數組是已經全部遍歷的,因此下面兩個while循環只有一個會執行
// 把左邊剩餘的數移入數組
while (i <= mid) {
temp[k++] = nums[i++];
}
// 把右邊邊剩餘的數移入數組
while (j <= high) {
temp[k++] = nums[j++];
}
// 最後把新數組中的數覆蓋nums數組
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}
public static void main(String[] args){
int array[] = {10,11,4,2,23,46,33,1};
int end = array.length - 1;
mergeSort.merge(array,0,end);
for (int num : array){
System.out.println(num);
}
}
}
快速排序
package others;
//快排
public class quickSort {
//快排
/**
* 快排的思想是,選擇一個元素,通常是對應區間的第一個元素,
* 將所有比他小的元素放到他的左邊
* 將所有比他大的元素放到他的右邊去
* */
public static int[] sort(int[] array,int start,int end){
//首先先判斷數組是否符合規定
if(array.length < 2 || array.length == 0 || start >= end){
return array;
}
int min = start;
int max = end;
if (min == max){
return array;
}
//保存臨時值,這裏的tempNum其實就是我們用來區分大數和小數的分界值,通常取第一個
int tempNum = array[min];
//當沒有結束時
while (min != max){
//先找到區間右側第一個比tempNum小的元素的位置
while (min < max && array[max] > tempNum){
max--;
}if (min<max){
quickSort.swap(array,min,max);
//然後交換兩個的位置,這樣一來max右側都是比tempNum大的數,同時也把這個比他小的值扔到了最前面去
++min;
}
//從區間左側找到第一個比tempNum大的元素的位置,然後交換兩個的位置,這樣min左側的數都比tempNum小,同時也把這個大數扔到了後面去
while (min < max && array[min] <= tempNum){
min++;
}
if (min < max) {
quickSort.swap(array,min,max);
--max;
}
//不斷循環
}
if (min == max){
array[max] = tempNum;
}
//遞歸調用sort對元素左側的區域來一次,對元素右邊的區域也來一次排序
array = sort(array,start,min-1);
array = sort(array,max + 1,end);
return array;
}
//這個函數是用於交換兩個元素的位置的
public static void swap(int []array,int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args){
int array[] = {10,11,4,2,23,46,33,1};
array = quickSort.sort(array,0,array.length-1);
for (int num : array){
System.out.println(num);
}
}
}
選擇排序
//選擇排序
package others;
// 每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最後,直到全部記錄排序完畢。
public class selectSort {
public static int[] srot(int[] array){
int p = 0;
int temp = 0;
if (array.length < 2 || array.length == 0){
return array;
}
for (int i = 0;i < array.length; i++){
temp = i;
for(int j = i; j < array.length; j++ ){
if (array[j] < array[temp]){
temp = j;
}
}
if (temp != i){
p = array[i];
array[i] = array[temp];
array[temp] = p;
}
}
return array;
}
public static void main(String[] args){
int array[] = {10,11,4,2,23,46,33,1};
array = selectSort.srot(array);
for (int num : array){
System.out.println(num);
}
}
}
希爾排序
/**
* 希爾排序的時間複雜度是不確定的
* 依賴於增量序列
* 時間複雜度在O(n1.3~n2)
*/
package others;
/**
* 先取一個小於n的整數d1作爲第一個增量,把文件的全部記錄分成d1個組。
* 所有距離爲dl的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;
* 然後,取第二個增量d2<d1重複上述的分組和排序,直至所取的增量dt=1(dt<dt-l<;…<d2<d1),即所有記錄放在同一組中進行直接插入排序爲止。
* 該方法實質上是一種分組插入方法。
* */
public class shellSort {
public static int [] sort(int[] array){
int temp = 0;
int t = 0;
if (array.length == 0 || array.length < 2){
return array;
}
temp = array.length;
while(true){
temp = temp / 2;
for (int i = 0;i < temp ;i++){
for (int index = i ;index < array.length ;index = index + temp){
for (int j = index; j < array.length; j = j + temp){
if((j + temp) < array.length) {
if (array[j] > array[j + temp]) {
t = array[j];
array[j] = array[j + temp];
array[j + temp] = t;
}
}
}
}
}
if (temp == 1)
break;
}
return array;
}
public static void main(String[] args){
int array[] = {10,11,4,2,23,46,33,1};
array = shellSort.sort(array);
for (int num : array){
System.out.println(num);
}
}
}
堆排序
import java.util.Arrays;
public class HeapSort {
//堆排序
public static void heapSort(int[] array) {
array = buildMaxHeap(array); //初始建堆,array[0]爲第一趟值最大的元素
for (int i = array.length - 1; i >= 1; i--) {
int temp = array[0]; //將堆頂元素和堆底元素交換,即得到當前最大元素正確的排序位置
array[0] = array[i];
array[i] = temp;
adjustHeap(array, 0, i); //整理,將剩餘的元素整理成大頂堆
}
}
//自下而上構建大頂堆:將array看成完全二叉樹的順序存儲結構
private static int[] buildMaxHeap(int[] array) {
//從最後一個節點array.length-1的父節點(array.length-1-1)/2開始,直到根節點0,反覆調整堆
for(int i=(array.length-2)/2;i>=0;i--){
adjustHeap(array, i, array.length);
}
return array;
}
private static void adjustHeap(int[] array, int k, int length) {
int k1=2*k+1;
if(k1<length-1 && array[k1]<array[k1+1]){
k1++;
}
if(k1>length-1||array[k]>=array[k1]){
return;
}else{
int temp = array[k]; //將堆頂元素和左右子結點中較大節點交換
array[k] = array[k1];
array[k1] = temp;
adjustHeap(array,k1,length);
}
}
public static void main(String[] args) {
int[] a = {87,45,78,32,17,65,53,9,122,133};
heapSort(a);
System.out.println(Arrays.toString(a));
}
}