Java - 排序大全
生活随笔
收集整理的這篇文章主要介紹了
Java - 排序大全
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本帖子包含的排序有:
1、庫函數的qsort()排序
2、冒泡排序
3、直接插入排序
4、折半插入排序
5、2-路·插入排序
6、希爾排序
7、快速排序
8、選擇排序
9、堆排序
10、歸并排序
11、基數排序
12、基于鏈表的冒泡排序
下面將一一貼出排序的代碼:
1、庫函數的qsort()排序
2、冒泡排序
/* * 冒泡排序:每一趟都將數組的第一個元素與第二個元素進行比較, * 若為逆序,則交換兩個元素的值,以此類推,每一趟 * 都把一個大的數放入到數組的后面,從而實現排序 * 時間復雜度:O(n^2) * 穩定性:穩定 */ void bubbleSort(int* array, int length) {for (int i = 0; i < length; ++i){for (int j = 0; j < length - i - 1; ++j){if (array[j] > array[j + 1]){array[j] ^= array[j + 1];array[j + 1] ^= array[j];array[j] ^= array[j + 1];}}} }3、直接插入排序
/* * 直接插入排序:是一種簡單的排序方法,基本操作是將一個記錄 * 插入到已排序好的有序表中,從而得到一個新的、 * 記錄數增1的有序表 * 時間復雜度:O(n^2) * 穩定性:穩定 */ void InsertSort(int* array, int length) {int sentry = 0;for (int i = 1; i < length; ++i){if (array[i] < array[i - 1]){sentry = array[i]; //設置崗哨array[i] = array[i - 1];int j = 0;for (j = i - 1; sentry < array[j]; --j) //將比崗哨小的元素往后移array[j + 1] = array[j];array[j + 1] = sentry; //插入到正確位置}} }4、折半插入排序
/* * 折半插入排序:由于插入排序的基本操作是在一個有序表中進行查找和插入,這個“查找”操作可以利用“折半查找” * 來實現,由此而來的折半插入排序 * 時間復雜度:O(n^2) * 穩定性:穩定 */ void BininsertSort(int* array, int length) {int sentry = 0, low, high, mid;int j = 0;for (int i = 1; i < length; ++i){sentry = array[i]; //將array[i]暫存在sentrylow = 0;high = i - 1;while (low <= high){mid = (low + high) / 2;if (sentry > array[mid])low = mid + 1;elsehigh = mid - 1;}for (j = i - 1; j > high; --j) //將數據往后移動array[j + 1] = array[j];array[j + 1] = sentry; //插入到正確位置} }5、2-路·插入排序
/* * 2-路插入排序:該排序是在折半插入排序的基礎上改進的,目的是減少排序過程中移動記錄的次數, * 但為此需要 n 個記錄的輔助空間 * 時間復雜度:O(n^2) * 穩定性:穩定 */ void InsertSort_2(int* array, int length) {int first = 0, final = 0; //分別表示在輔助空間的開始和最后的位置int* array_temp = new int[length] {0}; //創建輔助數組int k, i;array_temp[0] = array[0];for (i = 1; i < length; ++i){if (array[i] < array_temp[first]) //小于最小元素{first = (first - 1 + length) % length;array_temp[first] = array[i];}else if (array[i] > array_temp[final]) //大于最大元素{final = (final + 1 + length) % length;array_temp[final] = array[i];}else //折半查找{k = (final + 1 + length) % length;while (array_temp[((k - 1) + length) % length] > array[i]){array_temp[(k + length) % length] = array_temp[(k - 1 + length) % length];k = (k - 1 + length) % length;}array_temp[(k + length) % length] = array[i];final = (final + 1 + length) % length;}}for (k = 0; k < length; ++k) //拷貝數組array[k] = array_temp[(first + k) % length];delete[] array_temp; //釋放輔助空間 }6、希爾排序
/* * 希爾(Shell)排序:又稱“縮小增量排序”,基本思想是:先將整個待排記錄序列分割成若干子序列, * 分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄 * 進行一次直接插入排序 * 時間復雜度:O(nlog2n) * 穩定性:不穩定 */ void ShellSort(int* array, int length) {int interval = 1; //初始化一個間隔while (interval < length / 3) //設置最大間隔interval = interval * 3 + 1;while (interval > 0) //進行插入排序{long tmp = 0;for (int i = interval; i < length; ++i){tmp = array[i];int j = i;while (j > interval - 1 && array[j - interval] >= tmp){array[j] = array[j - interval];j -= interval;}array[j] = tmp;}interval = (interval - 1) / 3; //縮小間隔} }7、快速排序
/* * 快速排序(快排):是對冒泡排序的一種改進,它的基本思想是:通過一趟排序將待排序的記錄 * 分割成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分記錄的關鍵字小 * ,則可以分別對這兩部分記錄繼續進行排序,以達到整個序列有序 * 時間復雜度:O(nlog2n)--->當數組基本有序時,退化接近冒泡排序,時間復雜度為O(n^2) * 穩定性:不穩定 */ int Partition(int* arr, int low, int high)//首先需要一個函數返回軸驅的位置 這是每一排序的基礎 {/*交換數組當中的值 使軸驅記錄到自己該指定的位置 并返回其所在的位置 此時 軸驅前(后)的數值均不大(小)于軸驅位置上的數值*/int pivotkey = arr[low];while (low < high){while (low < high && arr[high] >= pivotkey)--high;arr[low] = arr[high];while (low < high && arr[low] <= pivotkey)++low;arr[high] = arr[low];}arr[low] = pivotkey;return low; } void QuickSort(int* arr, int low, int high) //注意,high應為數組最大個數減一 {/*利用上面函數返回值進行數組排序 快速排序*/if (low < high){int value = Partition(arr, low, high);QuickSort(arr, low, value - 1);QuickSort(arr, value + 1, high);} }8、選擇排序
/* * 選擇排序:每次選擇最小的數值,并且把最小數值賦給排序數組的前端,依次進行,直到數組有序 * 時間復雜度:O(n^2) * 穩定性:不穩定 */ void SelectSort(int* array, int length) {int i, j, min = 0, temp = 0;for (i = 0; i < length - 1; ++i){min = i; //查找最小值for (j = i + 1; j < length; ++j){if (array[min] > array[j])min = j;}if (min != i){//交換數值array[min] ^= array[i];array[i] ^= array[min];array[min] ^= array[i];}} }9、堆排序
/* * 堆排序:堆排序是利用堆這種數據結構而設計的一種排序算法,堆排序是一種選擇排序,堆是 * 具有以下性質的完全二叉樹:每個結點的值都大于或等于其左右孩子結點的值,稱為大頂堆; * 或者每個結點的值都小于或等于其左右孩子結點的值,稱為小頂堆 * 時間復雜度:O(nlog2n) * 穩定性:不穩定 */ void max_heapify(int* arr, int start, int end) {//建立父節點指標和子節點指標int dad = start;int son = dad * 2 + 1;while (son <= end){ //若子節點指標在范圍內才做比較if (son + 1 <= end && arr[son] < arr[son + 1]) //先比較兩個子節點大小,選擇最大的son++;if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數return;else{ //否則交換父子內容再繼續子節點和孫節點比較arr[dad] ^= arr[son];arr[son] ^= arr[dad];arr[dad] ^= arr[son];dad = son;son = dad * 2 + 1;}} } void heapsort(int* arr, int len) {//初始化,i從最後一個父節點開始調整for (int i = len / 2 - 1; i >= 0; i--)max_heapify(arr, i, len - 1);//先將第一個元素和已經排好的元素前一位做交換,再從新調整(剛調整的元素之前的元素),直到排序完畢for (int i = len - 1; i > 0; i--) {arr[0] ^= arr[i];arr[i] ^= arr[0];arr[0] ^= arr[i];max_heapify(arr, 0, i - 1);} }10、歸并排序
/* * 歸并排序:(MERGE-SORT)是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer) * 的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序 * 時間復雜度:O(nlog2n) * 穩定性:穩定 */ void _merge_inArray(int* array, int left, int mid, int right) //用來合并分開的數組 {int length = right - left + 1; //定義一個輔助空間的長度int* ptemp = new int[length] {0};//分配一個輔助數組//合并操作int low = left;//左邊區間起始下標int high = mid + 1;//右邊區間起始下標int index = 0;//輔助數組的下標while (high <= right) //右區間沒有合并完{while (low <= mid && array[low] <= array[high])//證明左區間沒有合并完,且左區間的值小于右區間的值ptemp[index++] = array[low++]; //把左邊的值放進輔助數組 low++表示左邊往高位移,//下一次需要判斷左邊的新下標,index++表示下一次放進輔助數組的新下標if (low > mid)//證明左區間已經放完break;while (high <= right && array[low] > array[high])ptemp[index++] = array[high++];}//到這一步證明有一個區間已經合并完成if (high <= right)//證明右邊沒有完成memmove(&ptemp[index], &array[high], sizeof(int) * (right - high + 1));if (low <= mid)//證明左邊沒有完成memmove(&ptemp[index], &array[low], sizeof(int) * (mid - low + 1));//把所有區間都合并到輔助區間memmove(&array[left], ptemp, sizeof(int) * length);delete[] ptemp; } void _merge(int* array, int left, int right)//將數組拆分成兩個左右區間 {if (left >= right) //遞歸終止操作,左右相等說明就只有一個元素,就不需要分了return;int mid = ((right - left) >> 1) + left; //求中點_merge(array, left, mid);//拆分左_merge(array, mid + 1, right);//拆分右//并操作_merge_inArray(array, left, mid, right); } void MergeSort(int* array, int length) {_merge(array, 0, length - 1); }11、基數排序
/* * 基數排序:(radix sort)屬于“分配式排序”(distribution sort),又稱“桶子法”(bucket sort) * 或bin sort,顧名思義,它是透過鍵值的部份資訊 * ,將要排序的元素分配至某些“桶”中,藉以達 * 到排序的作用 * 時間復雜度:O (nlog(r)m),其中r為所采取的基數,而m為堆數,在某些時候,基數排序法的效率高于其它的穩定性排序法。 * 穩定性:穩定 */ int maxbit(int* data, int n) //輔助函數,求數據的最大位數 {int d = 1; //保存最大的位數int p = 10;for (int i = 0; i < n; ++i){while (data[i] >= p){p *= 10;++d;}}return d; } void radixsort(int* array, int length) //基數排序 {int d = maxbit(array, length);int* tmp = new int[length];int* count = new int[10]; //計數器int i, j, k;int radix = 1;for (i = 1; i <= d; i++) //進行d次排序{for (j = 0; j < 10; j++)count[j] = 0; //每次分配前清空計數器for (j = 0; j < length; j++){k = (array[j] / radix) % 10; //統計每個桶中的記錄數count[k]++;}for (j = 1; j < 10; j++)count[j] = count[j - 1] + count[j]; //將tmp中的位置依次分配給每個桶for (j = length - 1; j >= 0; j--) //將所有桶中記錄依次收集到tmp中{k = (array[j] / radix) % 10;tmp[count[k] - 1] = array[j];count[k]--;}for (j = 0; j < length; j++) //將臨時數組的內容復制到data中array[j] = tmp[j];radix = radix * 10;}delete[]tmp;delete[]count; }12、基于鏈表的冒泡排序
/* * 使用冒泡排序思想對鏈表進行排序操作 */struct arr //鏈表的節點數據 {int data;arr* next; };arr* moveto(const arr node, int n) //將鏈表指針移動到指定位置,并返回 {arr* p = node.next;if (p){for (int i = 0; i < n; ++i){p = p->next;}}return p; }int count_list(arr node) //獲得鏈表長度 {int count = 0;arr* p = node.next;while (p){count++;p = p->next;}return count; }void create_list(arr* node, int length) //創建一個鏈表 {arr* p = node;arr* temp = NULL;for (int i = 0; i < length; ++i){temp = new arr;temp->data = rand() % length;temp->next = NULL;p->next = temp;p = p->next;}}void show_list(const arr node) //顯示鏈表數據 {arr* p = node.next;while (p){std::cout << p->data << " ";p = p->next;}std::cout << std::endl; }void destroy_list(arr* node) //銷毀鏈表 {arr* p = node;arr* temp = nullptr;while (p->next){temp = p->next;p->next = temp->next;free(temp);} }void list_sort(arr* node) //鏈表排序 {int count = count_list(*node);arr* p = nullptr;for (int i = 0; i < count - 1; ++i){for (int j = 0; j < count - 1 - i; ++j){p = moveto(*node, j);if (p){if (p->data > p->next->data){p->data ^= p->next->data;p->next->data ^= p->data;p->data ^= p->next->data;}}}} }使用的main函數
int main() {int array[13] = { 56, 95, 45, 21, 48, 75, 23, 11, 99, 33, 22, 44, 88 };//qsort(array,10,sizeof(int),mysort);//InsertSort(array, 13);//BininsertSort(array, 13);//InsertSort_2(array, 13);//ShellSort(array, 13);//QuickSort(array, 0, 12);//SelectSort(array, 13);//MergeSort(array, 13);//heapsort(array, 13);//radixsort(array, 13);arr head; //建立鏈表頭節點create_list(&head, 13); //創建鏈表list_sort(&head); //排序鏈表show_list(head); //顯示鏈表for (int i = 0; i < 13; ++i)std::cout << array[i] << " ";return 0; }總結
以上是生活随笔為你收集整理的Java - 排序大全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Ubuntu18版本下新安装Qtcr
- 下一篇: gcnew 与 new 的区别