J2SE I一一有多少你不知道的數據排序?

前言


排序,三大查找是《數據結構》當中很是基礎的知識點,在這裏爲了複習順帶總結了一下常見的排序算法。算法

經常使用比較排序算法的性能:數組

1、插入排序

基本思想:在一個已經排好序的序列中,將未被排序的元素按照原先序列的排序規則插入到序列中的指定位置。數據結構

經常使用舉例:直接插入排序性能

直接插入排序(Straight Insertion Sorting)是一種簡單的排序算法,他的基本思想是依次將每一個記錄插入到一個已經排好序的有序表中去,從而獲得一個新的、記錄增長1的有序表。具體過程以下:ui

初始序列:{45 38 66 90 88 10 25 }spa

第一步對前兩個數進行排序,把38插入到45以前,獲得新的序列{45 38 66 90 88 10 25}設計

第二步對前三個數進行排序,把66插入到有序序列{45 38}的合適位置,即{45 38 66 90 88 10 25}指針

之後的步驟是在都是在以上基礎上的一個遞歸過程知道最後一個數25插入到合適的位置獲得最終序列{10 25 38 45 66 88 90}code

算法描述:blog

<span style="font-family:KaiTi_GB2312;font-size:18px;">
void StraightInsertSort(List R,int n)
 //對順序表R進行直接插入排序
 {
 int i, j;
 for (i=2;i<=n;i++)//n爲表長,從第二個記錄起進行插入
 {
 R[0] = R[i];//第i個記錄複製爲崗哨
 j = i - 1;
 while (R[0].key<R[j].key)//與崗哨比較,直至鍵值不大於崗哨值
 {
 R[j +1]=R[j];//將第j個記錄賦值給第j+1個記錄
 j--;
 }
 R[j + 1] = R[0];//將第i個記錄插入的序列中
 }
 }</span>

2、交換排序

基本思想:比較兩個記錄的鍵值大小,若是兩個記錄鍵值的大小出現逆序,則交換這兩個記錄,這樣將鍵值較小的記錄向序列前部移動,鍵值較大的記錄向序列後部移動,最終將獲得有序序列。

(1)冒泡排序

冒泡排序法(Bubble Sorting)首先將第一個記錄的鍵值和第二個記錄的鍵值進行比較,若爲逆序則將這兩個記錄交換,而後繼續比較第二個和第三個記錄的鍵值。以此類推,直到完成第n-1個記錄和第n個記錄的鍵值比較交換爲止。這時便完成了第一趟氣泡,其結果是將最大的記錄移到最後一位。而後第二次氣泡跟第一次相似,其結果是將第二大的記錄移到倒數第二位。重複以上過程,直到整個排序過程終止獲得最終有序序列。

<span style="font-family:KaiTi_GB2312;font-size:18px;"> 
 void BubbletSort(List R,int n)
 {
 int i, j,temp,endsort;
 for (i=1;i<=n-1;i++)
 {
 endsort = 0;
 for (j = 1; j <= n - i - 1; j++)
 {
 if (R[j].key>R[j+1].key)//若爲逆序則交換記錄
 {
 temp = R[j];
 R[j] = R[j + 1];
 R[j + 1] = temp;
 endsort = 1;
 }
 }
 if (endsort == 0) break;
 }
 }</span>
### (2)快速排序

快速排序(Quick Sorting)是對冒泡排序的一種改進。它的基本思想是在n個記錄中取某一個記錄的鍵值爲標準,一般取第一個記錄鍵值爲基準,經過一趟排序將待排序的記錄分爲小於等於這個鍵值和大於這個鍵值的兩個獨立的部分,這時前面部分的記錄鍵值均比後面的記錄鍵值小,而後對這兩部分分別按照這種方法排序,直到得到整個有序序列。

算法描述:

<span style="font-family:KaiTi_GB2312;font-size:18px;">
//第一趟快速排序算法
 int QuickPartition(List R,int low,int hign)
 {
 x=R[low]//賦初值,標準數
 while (low < hign)
 {
 while ((low <hign) && (R[hign].key>=x.key )) hign--;
 R[low]=R[hign];//自尾端進行比較,將比x小的記錄移到低端
 while ((low <hign) && (R[low].key<=x.key )) low++;
 R[hign]=R[low];//自首端進行比較,將比x大的記錄移到高端
 }
 R[low]=x;//第一趟排序結束,將x移到其最終位置
 return low ;
 }</span>

3、選擇排序

基本思想:每次在n-i+1(i=1,2,3……,n-1)個記錄中選取鍵值最小的記錄做爲有序序列的第i個記錄。

經常使用舉例:直接選擇排序、堆排序。

(1)直接選擇排序

直接選擇排序(Selection Sorting)的基本思想是在第i次選擇操做中,經過n-i次鍵值比較,從n-i+1個記錄中選出最小的記錄,並和第i(1<=i<=n-1)個記錄交換。

算法描述:

<span style="font-family:KaiTi_GB2312;font-size:18px;">        
void SelectSort(List R,int n)
 {
 int min, i, j;
 for(i=1;i<=n-1;i++)//每次循環選擇出最小一個鍵值
 {
 min=i;//假設第i個記錄鍵值最小
 for(j=i+1;j<=n;j++)
 {
 if(R[j].key<R[min].key) min =j;//記錄下鍵值最小記錄的下標
 if(min!=i) swap(R[min],R[i]);//將最小鍵值記錄和第i個記錄交換
 }
 }
 }</span>

(2)堆排序

堆排序(Heap Sorting)是利用堆的數據結構所設計的一種排序算法,可利用數組的特色快速定位指定索引的元素。堆分爲最大堆和最小堆,最大堆中的任一節點的值都不小於它的兩個孩子的值(若存在孩子的話);最小堆則任一節點的值都不大於它的兩個孩子的值。

算法描述:

<span style="font-family:KaiTi_GB2312;font-size:18px;">
void Sift(List R,int k,int m)
 {
 int i, j, x;
 List t;
 i = k; j = 2 * i;
 x = R[k].key;
 t = R[k];
 while (j<=m)
 {
 if ((j < m) && (R[j].key > R[j + 1].key))
 j++;//若存在右子樹且右子樹的關鍵字小,則沿右分支篩選
 if (x < R[j].key) break;//篩選完畢
 else
 {
 R[i] = R[j];
 i = j;
 j = 2 * i;
 }
 R[i] = t;//填入適當位置
 }
 }
 //堆排序算法
 void HeapSort(List R)
 {
 int i;
 for (i = n / 2; i >= 1; i--)
 Shit(R, i, n);//從第n/2個記錄開始進行篩選建堆
 for (i=n;i>=2;i--)
 {
 swap(R[1], R[i]);//將堆頂記錄和堆中最後一個記錄互換
 Sift(R, 1, i - 1);//調整R[1]使R[1],……,R[i-1]變成堆
 }
 }</span>

4、歸併排序

基本思想:

1)將已經有序的子序列合併,獲得徹底有序的序列,

2)先使每一個子序列有序,再使子序列段間有序

3)若將兩個有序表合併成一個有序表稱爲二路歸併

常見舉例:

二路歸併排序。

二路歸併排序是將兩個有序表結合成一個有序表,基本思想是假設序列中有n個記錄,可當作是n個有序的子序列,每一個序列的長度爲1.首先將每相鄰的兩個記錄合併,獲得n/2(向上取整)個較大的有序序列,每一個子序列包含2個記錄,再將上述子序列兩兩合併,獲得(n/2)/2(向上取整)個有序序列,如此反覆,知道獲得最終有序序列爲止。

步驟:

a 申請空間,讓他大小爲兩個已經排序的序列之和,

該空間用來存放合併後的序列

b 設定兩個指針,最初位置分別爲兩個已經排序序列起始位置

c 比較兩個指針所指向的元素,選擇相對較小的放入合併空間,並移動

指針到下一個位置

d 重複步驟c 知道某個指針達到序列尾

e 將另外一個序列剩下的全部元素直接複製到合併序列尾。

//歸併排序
void Merge(int a[], int left, int mid,int right)
{
 int size = right - left + 1;
 int *temp = (int *)malloc(size*sizeof(int));
 int i = left;
 int j = mid + 1;
 int index = 0;
 while (i <= mid && j <= right)
 {
 temp[index++] = a[i] < a[j] ? a[i++] : a[j++];
 }
 while (i <= mid)
 {
 temp[index++] = a[i++];
 }
 while (j <= right)
 {
 temp[index++] = a[j++];
 }
 for (int k = 0; k < size; k++)
 {
 a[left++] = temp[k];
 }
}
void MergeSort(int a[], int left, int right)
{
 if (left == right) return;
 int mid = left + ((right - left) >> 1);
 MergeSort(a, left, mid);
 MergeSort(a, mid + 1, right);
 Merge(a, left, mid, right);
}

五.基數排序

基數排序:經過序列中各個元素的值,對排序的N個元素進行若干趟的「分配」與「收集」來實現排序。

分配:咱們將L[i]中的元素取出,首先肯定其個位上的數字,根據該數字分配到與之序號相同的桶中

收集:當序列中全部的元素都分配到對應的桶中,再按照順序依次將桶中的元素收集造成新的一個待排序列L[ ]

對新造成的序列L[]重複執行分配和收集元素中的十位、百位...直到分配完該序列中的最高位,則排序結束

看到這裏屬實不容易了,點亮當心心喔~

相關文章
相關標籤/搜索