前言
博主最近在惡補基礎知識,算法必然是必不可少的,那麼就從經典排序算法開始吧!(圖源網絡,侵刪),沒有列出全部,因爲在期末考試囧
代碼太多,就只顯示了最關鍵的部分
1. 冒泡排序
實現思路:
(1)比較前後相鄰的二個數據,如果前面數據大於後面的數據,就將這二個數據交換。
(2)這樣對數組的第0個數據到N-1個數據進行一次遍歷後,最大的一個數據就“沉”到數組第 N-1個位置。
(3)N=N-1,如果N不爲 0就重複前面二步,否則排序完成。
這也是博主接觸到的第一個排序算法
public static void bubbleSort1(){
int i, j;
for(i=0; i<n; i++){//表示 n次排序過程。
for(j=1; j<n-i; j++){
if(a[j-1] > a[j]){//前面的數字大於後面的數字就交換
//交換a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
}
}
}
}
圖示:
2. 插入排序算法
通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應的位置並插入。如果輸入數組已經是排好序的話,插入排序出現最佳情況,其運行時間是輸入規模的一個線性函 數。如果輸入數組是逆序排列的,將出現最壞情況。平均情況與最壞情況一樣,其時間代價是(n2)。
public void sort()
{
for(int i =1; i<arr.length;i++)
{
//插入的數
int insertVal = arr[i];
//被插入的位置(準備和前一個數比較)
int index = i-1;
//如果插入的數比被插入的數小
while(index>=0&&insertVal<arr[index])
{
//將把arr[index] 向後移動
arr[index+1]=arr[index];
//讓index向前移動
index--;
}
//把插入的數放入合適位置
arr[index+1]=insertVal;
}
}
圖示:
3. 快速排序算法
快速排序的原理:選擇一個關鍵值作爲基準值。比基準值小的都在左邊序列(一般是無序的), 比基準值大的都在右邊(一般是無序的)。一般選擇序列的第一個元素。
public void sort(){
int start = low;
int end = high;
int key = a[low];
while(end>start){
//從後往前比較
while(end>start&&a[end]>=key)
//如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置,然後又從前往後比較
end--;
if(a[end]<=key){
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
//從前往後比較
while(end>start&&a[start]<=key)
//如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
start++;
if(a[start]>=key){
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
//此時第一次循環比較結束,關鍵值的位置已經確定了。左邊的值都比關鍵值小,右邊的 值都比關鍵值大,但是兩邊的順序還有可能是不一樣的,進行下面的遞歸調用
}
//遞歸
if(start>low) sort(a,low,start-1);//左邊序列。第一個索引位置到關鍵值索引-1
if(end<high) sort(a,end+1,high);//右邊序列。從關鍵值索引+1到最後一個
}
}
圖示:
4. 希爾排序
基本思想:先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,待整個序列 中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。
- 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個數k,對序列進行k 趟排序;
- 每趟排序,根據對應的增量 ti,將待排序列分割成若干長度爲 m 的子序列,分別對各子表進 行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。
private void shellSort() {
int dk = a.length/2;
while( dk >= 1 ){
ShellInsertSort(a, dk);
dk = dk/2;
}
}
private void ShellInsertSort(int[] a, int dk) {
//類似插入排序,只是插入排序增量是1,這裏增量是dk,把1換成dk就可以了
for(int i=dk;i<a.length;i++){
if(a[i]<a[i-dk]){
int j;
int x=a[i];//x爲待插入元素
a[i]=a[i-dk];
for(j=i-dk; j>=0 && x<a[j];j=j-dk){
//通過循環,逐個後移一位找到要插入的位置。
a[j+dk]=a[j];
}
a[j+dk]=x;//插入
}
}
}
圖示:
5. 歸併排序算法
歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列 分爲若干個子序列,每個子序列是有序的。然後再把有序子序列合併爲整體有序序列
public class MergeSortTest (){
public static void main(String[] args) {
int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
print(data);
mergeSort(data);
System.out.println("排序後的數組:");
print(data);
}
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中間索引
int center = (left + right) / 2;
// 對左邊數組進行遞歸
sort(data, left, center);
// 對右邊數組進行遞歸
sort(data, center + 1, right);
// 合併
merge(data, left, center, right);
print(data);
}
/**
* 將兩個數組進行歸併,歸併前面2個數組已有序,歸併後依然有序
*
* @param data
* 數組對象
* @param left
* 左數組的第一個元素的索引
* @param center
* 左數組的最後一個元素的索引,center+1是右數組第一個元素的索引
* @param right
* 右數組最後一個元素的索引
*/
public static void merge() {
// 臨時數組
int[] tmpArr = new int[data.length];
// 右數組第一個元素索引
int mid = center + 1;
// third 記錄臨時數組的索引
int third = left;
// 緩存左數組第一個元素的索引
int tmp = left;
while (left <= center && mid <= right) {
// 從兩個數組中取出最小的放入臨時數組
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
// 剩餘部分依次放入臨時數組(實際上兩個while只會執行其中一個)
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
// 將臨時數組中的內容拷貝回原數組中
// (原left-right範圍的內容被複制回原數組)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
圖示:
6. 桶排序算法
桶排序的基本思想是: 把數組 arr 劃分爲 n 個大小相同子區間(桶),每個子區間各自排序,最 後合併 。計數排序是桶排序的一種特殊情況,可以把計數排序當成每個桶裏只有一個元素的情況。
- 找出待排序數組中的最大值max、最小值min
- 我們使用 動態數組 ArrayList 作爲桶,桶裏放的元素也用 ArrayList 存儲。桶的數量爲(maxmin)/arr.length+1
- 遍歷數組 arr,計算每個元素 arr[i] 放的桶
- 每個桶各自排序
public static void bucketSort(){
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
//創建桶
int bucketNum = (max - min) / arr.length + 1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for(int i = 0; i < bucketNum; i++){
bucketArr.add(new ArrayList<Integer>());
} //將每個元素放入桶
for(int i = 0; i < arr.length; i++){
int num = (arr[i] - min) / (arr.length);
bucketArr.get(num).add(arr[i]); }
//對每個桶進行排序
for(int i = 0; i < bucketArr.size(); i++){
Collections.sort(bucketArr.get(i));
}
}
}
圖示: