排序演算法——插入排序
直接插入排序
最簡單的排序方法。它的基本操作是將一個記錄插入到已經排好序的有序表中,從而得到一個新的、記錄增1的有序表。
把n個待排序的元素看成一個有序表和一個無序表,開始時有序表中只有一個元素,無序表中有n-1個元素;排序過程即每次從無序表中取出第一個元素,將它插入到有序表中,使之成為新的有序表,重複n-1次完成整個排序過程。
0.初始狀態 3,1,5,7,2,4,9,6(共8個數)
有序表:3;無序表:1,5,7,2,4,9,6
1.第一次迴圈,從無序表中取出第一個數 1,把它插入到有序表中,使新的數列依舊有序
有序表:1,3;無序表:5,7,2,4,9,6
2.第二次迴圈,從無序表中取出第一個數 5,把它插入到有序表中,使新的數列依舊有序
有序表:1,3,5;無序表:7,2,4,9,6
3.第三次迴圈,從無序表中取出第一個數 7,把它插入到有序表中,使新的數列依舊有序
有序表:1,3,5,7;無序表:2,4,9,6
4.第四次迴圈,從無序表中取出第一個數 2,把它插入到有序表中,使新的數列依舊有序
有序表:1,2,3,5,7;無序表:4,9,6
5.第五次迴圈,從無序表中取出第一個數 4,把它插入到有序表中,使新的數列依舊有序
有序表:1,2,3,4,5,7;無序表:9,6
6.第六次迴圈,從無序表中取出第一個數 9,把它插入到有序表中,使新的數列依舊有序
有序表:1,2,3,4,5,7,9;無序表:6
7.第七次迴圈,從無序表中取出第一個數 6,把它插入到有序表中,使新的數列依舊有序
有序表:1,2,3,4,5,6,7,9;無序表:(空)
程式:
//直接插入排序 //升序排序 #include<stdio.h> void InsertSort(int *a,int n) { int i,j,tmp; for(i=1;i<n;i++) { if(a[i-1]>a[i]) { tmp=a[i]; j=i; while(j&&tmp<a[j-1]) { a[j]=a[j-1]; j--; } a[j]=tmp; } } } int main() { int i; int a[]={1,2,8,5,6,9,4,2,7,5}; int n=sizeof(a)/sizeof(int); InsertSort(a,n); for(i=0;i<n;i++) printf("%d ",a[i]); return 0; }
直接插入排序的時間複雜度是o(n2) ;
折半插入排序
由於直接插入排序的前方資料已經基本有序,有時順序查詢很費時。因而產生了“折半”查詢的排序。
程式:
//折半插入排序
//升序排列
#include<stdio.h>
using namespace std;
void BInsertSort(int *a,int n)
{
int i,j,low,high,m,tmp;
for(i=1;i<n;i++)
{
if(a[i]<a[i-1])
{
low=0;
high=i-1;
tmp=a[i];
m=(low+high)/2;
while(low<high)//最後low==high跳出時,m=low=high
{ //因而總體來說,m最後記錄的是插入位置
if(tmp<a[m])
high=m-1;
else if(tmp>a[m])
low=m+1;
else
break;
m=(low+high)/2;
}
for(j=i;j>m;j--)
a[j]=a[j-1];
a[j]=tmp;
}
}
}
int main()
{
int i;
int a[]={4,5,9,6,3,8,2,8,2,8,6,6,5,4,2,8,9,5};
int n=sizeof(a)/sizeof(int);
BInsertSort(a,n);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
希爾排序
插入排序在基本有序的情況下效率挺高,希爾排序可使程式部分逐漸變得有序。
一. 演算法描述
希爾排序:將無序陣列分割為若干個子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,對各個子序列進行插入排序;然後再選擇一個更小的增量,再將陣列分割為多個子序列進行排序......最後選擇增量為1,即使用直接插入排序,使最終陣列成為有序。
增量的選擇:在每趟的排序過程都有一個增量,至少滿足一個規則 增量關係 d[1] > d[2] > d[3] >..> d[t] = 1 (t趟排序);根據增量序列的選取其時間複雜度也會有變化,這個不少論文進行了研究,在此處就不再深究;本文采用首選增量為n/2,以此遞推,每次增量為原先的1/2,直到增量為1;
下圖詳細講解了一次希爾排序的過程:
--------------------- 本文來自 love小仙 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/jianfpeng241241/article/details/51707618?utm_source=copy
程式碼:
//希爾排序(升序)
#include<stdio.h>
void ShellInsert(int *a,int n)
{
int dk[]={5,3,1};
int dk_len=sizeof(dk)/sizeof(int);
int i,j,k,tmp1,tmp2;
for(i=0;i<dk_len;i++)
{
for(j=0;j<dk[i];j++)
{
for(k=j+dk[i];k<n;k+=dk[i])
{
if(a[k]<a[k-dk[i]])
{
tmp1=k;
tmp2=a[k];
while(tmp1>j&&tmp2<a[tmp1-dk[i]])
{
a[tmp1]=a[tmp1-dk[i]];
tmp1-=dk[i];
}
a[tmp1]=tmp2;
}
}
}
}
}
int main()
{
int i;
int a[]={8,2,5,8,7,4,2,6,3,85,62,5,4,3,2,22,25,87};
int n=sizeof(a)/sizeof(int);
ShellInsert(a,n);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
參考文章: