筆試之排序-直接插入排序、氣泡排序、快速排序
1. 插入排序
插入排序是一種簡單直觀的排序方法,其基本思想在於每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子序列中,直到全部記錄插入完成。
由插入排序的思想可以引申出兩個重要的排序演算法:直接插入排序和希爾排序。
直接插入虛擬碼:
void InsertSort(ElemType A[], int n)
{
int i ,j;
for(i = 2;i<=n;i++) //依次將A[1]~A[n]插入到前面已排序序列
if(A[i].key<A[i-1].key)
{
A[0].key = A[i].key; //待插入值複製為哨兵
for(j = i-1;A[0].key<A[j].key;j--) //從後往前查詢待插入位置
A[j+1] = A[j]; //後移
A[j+1] = A[0]; //將哨兵插入到空位
}
}
直接插入排序的時間複雜度是O(n^2),空間複雜度為O(1)
在最好的情況下,表中元素已經有序,此時每插入一個元素,都只需比較一次而不用移動元素,因而時間複雜度為O(n)
穩定性:由於每次插入元素總是從後向前先比較再移動,所以不會出現相同元素相對位置發生變化的情況,即直接插入排序是一個穩定的排序方法。
2. 交換排序
所謂交換,就是根據序列中兩個元素關鍵字的比較結果來對換這兩個記錄在序列中的位置。
氣泡排序
氣泡排序演算法基本思想是:假設待排序表長為n,從後往前(或從前往後)兩兩比較相鄰元素的值,若為逆序(即A[i-1]>A[i]),則交換它們,直到序列比較完。
氣泡排序虛擬碼:
void BubbleSort(ElemType A[], int n)
{
//用氣泡排序將序列A中的元素從小到大排列
for (int i = 0; i < n; i++)
{
flag = false; //表示本趟冒泡是否發生交換的標誌
for (int j = n-1; j > i ; j--)
{
if(A[j-1].key>A[j].key)
{
swap(&A[j-1], &A[j]); //這裡有一個空間複雜度
flag = true;
}
}
if(flag == false)
return ; //本趟遍歷後沒有發生交換,說明已經有序
}
}
氣泡排序演算法的效能分析:空間複雜度O(1),最壞情況下時間複雜度為O(n^2),最好的情況下(表示元素基本有序)時間複雜度為O(n),其平均複雜度為O(n^2)
氣泡排序是一個穩定的排序。
3. 快速排序
快速排序是對氣泡排序的一種改進。其基本思想是基於分治法的。想詳細瞭解的朋友請轉到http://blog.csdn.net/v_JULY_v/article/details/6116297
完整程式碼:
#include<stdio.h>
#include<exception>
#include<stdlib.h>
#include<string.h>
void Swap(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int Partition(int data[], int length, int start , int end)
{
if(data == NULL || length<0 || start<0 || end>=length)
throw new std::exception("invalid parameters");
int index =(int)(start + end)/2; //產生start到end間的隨機數
int small = start - 1;
Swap(&data[index], &data[end]);
for (int i = start; i < end; i++)
{
if(data[i]<data[end])
{
small++;
if(small != i)
Swap(&data[small], &data[i]);
}
}
++small;
Swap(&data[small], &data[end]);
return small;
}
void QuickSort(int data[], int length, int start, int end)
{
if(start == end)
return;
int index = Partition(data, length, start,end);
if(index>start)
QuickSort(data,length,start,index-1);
if(index<end)
QuickSort(data,length,index+1,end);
}
void Test(int dataS[], int dataD[], int length)
{
while(length>=0)
{
if(dataS[length]!=dataD[length])
break;
length--;
}
if(length>=0)
printf("failed");
else
printf("success");
}
int main()
{
int data[] = {2,8,3,7,1,5,6,4};
QuickSort(data,8,0,7);
int expectedData[]={1,2,3,4,5,6,7,8};
Test(data,expectedData,7);
getchar();
return 0;
}
快速排序演算法的效能分析:
空間效率:由於快速排序是遞迴的,需要藉助一個遞迴工作棧來儲存每一層遞迴呼叫的必要資訊,其容量應與隊規呼叫的最大深度一致。最好情況下為取上界的log2(n+1);最壞的情況下,因為要進行n-1次遞迴呼叫,所以棧深度為O(n):平均情況為O(log2n)
時間效率:快速排序的執行時間與劃分是否對稱有關,而後者又與具體使用的劃分演算法有關。快速排序的最壞情況發生在兩個區域分別包含n-1個元素和0個元素時,這種最大程度的不對稱性發生在每一層遞迴上,即對應於初始排序表基本有序或基本逆序時,就得到最壞情況下的時間複雜度O(n^2)
有很多方法可以提高演算法的效率。一種方法是當遞迴過程中劃分得到的子序列的規模較小時不要再繼續遞迴呼叫快速排序,可以採用直接插入排序演算法進行後續的排序工作。另一種方法就是儘量選取一個可以將資料中分的樞軸元素。可以用三分法或者隨機法,這樣使得最壞情況在實際排序中基本不會出現。
時間複雜度O(nlog2n)
快速排序是一種不穩定的排序
相關文章
- 排序:氣泡排序&快速排序排序
- PHP 常見4種排序 氣泡排序、選擇排序、插入排序、快速排序PHP排序
- 9. 氣泡排序,以及如何優化氣泡排序,氣泡排序屬於插入排序排序優化
- 氣泡排序 插入排序 快排排序
- python實現氣泡排序、插入排序以及快速排序演算法Python排序演算法
- php實現 氣泡排序,插入排序,選擇排序PHP排序
- go 實現氣泡排序和插入排序Go排序
- 排序演算法(氣泡排序,選擇排序,插入排序,希爾排序)排序演算法
- Python八大演算法的實現,插入排序、希爾排序、氣泡排序、快速排序、直接選擇排序、堆排序、歸併排序、基數排序。Python演算法排序
- 用JS實現氣泡排序和插入排序JS排序
- 排序——氣泡排序排序
- 氣泡排序、歸併排序與快速排序比較排序
- 【JS面試向】選擇排序、桶排序、氣泡排序和快速排序簡介JS面試排序
- Go實現氣泡排序和快速排序Go排序
- 【C語言】氣泡排序與快速排序C語言排序
- 氣泡排序筆記排序筆記
- 演算法之常見排序演算法-氣泡排序、歸併排序、快速排序演算法排序
- Java實現氣泡排序和插入排序演算法Java排序演算法
- Java排序演算法之氣泡排序Java排序演算法
- 三種插入排序 直接插入排序,折半插入排序,希爾排序排序
- 氣泡排序排序
- 重學資料結構和演算法(四)之氣泡排序、插入排序、選擇排序資料結構演算法排序
- 【小小前端】前端排序演算法第一期(氣泡排序、選擇排序、插入排序)前端排序演算法
- OJ題之氣泡排序排序
- 排序演算法--氣泡排序排序演算法
- 排序演算法__氣泡排序排序演算法
- 排序演算法–氣泡排序排序演算法
- 選擇排序和氣泡排序排序
- 氣泡排序與選擇排序排序
- 【排序】氣泡排序(待補充)排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- js氣泡排序JS排序
- JavaScript氣泡排序JavaScript排序
- 氣泡排序1排序
- 氣泡排序-fusha排序
- 氣泡排序演示排序
- Shell氣泡排序排序
- d氣泡排序排序
- 容器氣泡排序排序