經典的幾種排序方式

所謂排序就是整理文件中的記錄,使之按關鍵字遞增(或遞減)次序排列起來。
穩定排序與不穩定排序:
假設 Ki = Kj ,且排序前序列中 Ri 領先於 Rj ;
若在排序後的序列中 Ri 仍領先於 Rj ,則稱排序方法是穩定的。
若在排序後的序列中 Rj 仍領先於 Ri ,則稱排序方法是不穩定的。
例:序列 3 15 8 8 6 9

若排序後得 3 6 8 8 9 15 穩定的#兩個8 不同順序
若排序後得 3 6 8 8 9 15 不穩定的
根據排序過程中待排序記錄是否全部放置在內存中,排序分爲內排和外排。

內部排序: 指的是待排序記錄存放在計算機隨機存儲器中進行的排序過程。
外部排序: 指的是待排序記錄的數量很大,以致內存一次不能容納全部記錄,在排序過程中尚需對外存進行訪問的排序過程。
算法的複雜性:體現在運行該算法時的計算機所需資源的多少上,計算機資源最重要的是時間和空間(即寄存器)資源,因此複雜度分爲時間和空間複雜度。

輔助空間:輔助空間是評價排序算法的一個重要指標,輔助空間是指除了存放待排序資源之外,執行算法所需要的其他存儲空間。

時間複雜度:簡單的說就是程序循環執行的總的次數。算法的時間複雜度是一個函數,它定量描述了該算法的運行時間。時間複雜度常用大O符號表述,即O(f(n))。

按照排序過程中所依據的原則的不同可以分類爲:

►插入排序
    直接插入排序  希爾排序
►交換排序
    冒泡排序  快速排序
►選擇排序
    簡單選擇排序  堆排序
►歸併排序

►基數排序

介紹幾種已經掌握的排序方法:
直接插入排序:
對於給定的一組記錄,初始時假定第一個記錄自成一個有序的序列,其餘的記錄爲無序序列;接着從第二個記錄開始,按照記錄的大小依次將當前處理的記錄插入到其之前的有序序列中,直至最後一個記錄插入到有序序列爲止。
例:將 29 18 87 56 3 27 按由小到大排序
① (29) (18 87 56 3 27)
② (18 29) (87 56 3 27)
③ (18 29 87) (56 3 27)
④ (18 29 56 87) (3 27)
⑤ ( 3 18 29 56 87) (27)
⑥ (3 18 27 29 56 87)
具體的程序看下:(由於頭文件寫了不好上傳 請用時自行加上 下面也是)
int main()
{
int i,j,temp,length;
int a[5] = {8, 7, 3, 5, 1};
length = sizeof(a)/sizeof(a[0]);
for(i = 1; i < length; i++)
{
temp = a[i];
for(j = i-1 ;j >= 0; j–)
{
if(temp < a[j])
{
a[j+1]= a[j];
}
else
{
break;
}
}
a[j+1] = temp;
}

for(i = 0; i < length; i++)
{
    printf("%d",a[i]);
}
printf("\n");
return 0;

}
穩 定 性:穩定

時間複雜度: O(n^2)
(1)初始數據正序,總比較次數:n-1
(2)初始數據逆序,總比較次數:(n2+n-1)/2= O(n2)
(3)初始數據無序,第i趟平均比較次數(i+1)/2,總次數爲:(n2+3n)/4=O(n2)
(4)可見,原始數據越趨向正序,比較次數和移動次數越少。

希爾排序:
希爾排序也稱爲“縮小增量排序”,基本原理是:首先將待排序的元素分爲多個子序列,使得每個子序的元素個數相對較少,對各個子序分別進行直接插入排序,待整個待排序序列“基本有序後”,再對所有元素進行一次直接插入排序。
希爾排序的特點:

時間複雜度:希爾排序的時間複雜性在O(nlog2n)和O(n2 )之間,大致爲O(n1.3)。

穩 定 性:不穩定
具體程序如下:
int main()
{
int a[] = {2,5,7,25,89,105,34};
int length,i,j,temp,gap;
length = sizeof(a)/ sizeof(a[0]);
for(gap = length/2; gap > 0; gap /= 2)
{
for(i = gap; i < length; i++ )
{
temp = a[i];
for(j = i - gap; j >= 0 && temp < a[j];j=j-gap)
{
a[j+gap] = a[j];
}
a[j+gap]= temp;
}
}
for(i = 0; i < length; i++)
{
printf(“%d “,a[i]);
}
printf(“\n”);
return 0;
}

快速排序:
快速排序是一種非常高效的排序方法,採用“分而治之”的思想,把大的拆分爲小的,小的在拆分爲更小的。
原理是:對於一組給定的記錄,通過一趟排序後,將原序列分爲兩部分,其中前部分的所有記錄均比後部分的所有記錄小,然後再依次對前後兩部分的記錄進行快速排序,遞歸該過程,直到序列中的所有記錄均爲有序爲止
快速排序特點:

穩 定 性:不穩定

平均時間複雜度: O(nlog2n)
程序如下:
void Sort(int *a,int low,int high)
{
int i,j;
int index;

i = low;
j = high;
index = a[i];

if(low >= high)
{
    return;
}

while(i < j)
{
    while(i < j && a[j] >= index)
    {
        j--;
    }
    if(i < j)
    {
        a[i++] = a[j];
    }
    while(i < j && a[i] < index)
    {
        i++;
    }
    if(i < j)
    {
        a[j--] = a[i];
    }
}
a[i] = index;
Sort(a,low,i - 1);
Sort(a,i + 1,high);

}

void QuickSort(int a[], int length)
{
Sort(a,0,length - 1);
}

int main()
{
int a[] = {9, 8, 15, 78, 54, 89, 21, 36};
int i;
int length = sizeof(a) /sizeof(a[0]);
QuickSort(a,length);
for(i = 0; i < length; i++)
{
printf(“%d “,a[i]);
}
printf(“\n”);
return 0;
}

歸併排序:
利用遞歸與分治技術將數據序列劃分爲越來越小的半子表,再對半子表排序,最後再用遞歸步驟將排好序的半子表合併成爲越來越大的有序序列。
原理如下:對於給定的一組記錄,首先將兩個相鄰的長度爲1的子序列進行歸併,得到n/2個長度爲2或者1的有序子序列,在將其兩兩歸併,反覆執行此過程,直到得到一個有序的序列爲止。
例:將49 38 65 97 76 13 27由小到大排序
初始化關鍵字:[49] [38] [65] [97] [76] [13] [27]

一趟歸併後: [38 49] [65 97] [13 76] [27]

二趟歸併後: [38 49 65 97] [13 27 76]

三趟歸併後: [13 27 38 49 65 76 97]
歸併排序特點:

平均時間複雜度: O(nlog2n)

穩 定 性: 穩定
程序如下:
void merging(int a[],int begin,int mid,int end)
{
int tmp = (int )malloc(sizeof(int)*(end - begin + 1));
int i,j,k;
i = begin;
j = mid + 1;
k = 0;

while(i <= mid && j <=end)
{
    if(a[i] < a[j])
        tmp[k++] = a[i++];
    else
        tmp[k++] = a[j++];
}

while(i <= mid)
    tmp[k++] = a[i++];
while(j <= end)
    tmp[k++] = a[j++];

for(i = 0;i < k;i++)
{
    a[begin + i] = tmp[i];
}
free(tmp);

}
void merge_sort(int a[],int begin,int end)
{
int mid;
if(a == NULL || begin >= end)
return;
mid = (begin + end) / 2;
merge_sort(a,begin,mid);
merge_sort(a,mid + 1,end);
merging(a,begin,mid,end);

}
int main()
{
int i,length;
int a[10] = {0};
printf(“enter 10 num…\n”);
for(i = 0;i < 10;i++)
{
scanf(“%d”,&a[i]);
}
length = sizeof(a)/sizeof(int);

merge_sort(a,0,length - 1);

for(i = 0;i < length;i++)
{
    printf("%d  ",a[i]);
}
return 0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章