1、插入排序
基本原理:
插入排序的原理与很多人打牌时,整理手中牌时的做法差不多。在开始摸牌时,我们的左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的每一张牌从右到左地进行比较。无论在什么时候,左手中的牌都是排好序的,而这些牌原先都是桌上那副牌里最顶上的一些牌(摘自《算法导论》)
时间复杂度:O(n^2)
代码实现:
#include<stdio.h>
#define N 10
int A[N] ;
void InsertSort(/*int A[],*/int n) ;
int main(void)
{
int i = 0 ;
int n = 0 ;
freopen("in.txt","r",stdin) ;
while(scanf("%d",&n) != EOF)
{
for(i = 0 ; i < n ; ++i)
{
scanf("%d",&A[i]) ;
}
printf("You have Input the List:\n") ;
for(i = 0 ; i < n ; ++i)
{
printf("%-2d",A[i]) ;
}
printf("\n") ;
InsertSort(/*A,*/n) ;
printf("After Sort:\n") ;
for(i = 0 ; i < n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n\n\n") ;
}
return 0 ;
}
void InsertSort(/*int A[],*/int n)
{
int i,j ;
int nKey = 0 ;
for(i = 0 ; i < n ; ++i)
{
nKey = A[i] ;
j = i - 1 ;
while(j>=0 && A[j] > nKey)
{
A[j+1] = A[j] ;
j-- ;
}
A[j+1] = nKey ;
}
}
插入排序递归版:
基本原理:为排序A[1..n], 先递归地排序A[1..n-1],然后再将A[n]插入到已排序的数组A[1..n-1]中去。(摘自《算法导论》)
代码实现:
#include<stdio.h>
#define N 10
int A[N] ;
void RecurInsertSort(/*int A[],*/int n) ;
void Insert(/*int A[]*/,int n,int nKey) ;
int main(void)
{
int n ,i;
freopen("in.txt","r",stdin) ;
while(scanf("%d",&n) != EOF)
{
for(i = 0 ; i < n ; ++i)
{
scanf("%d",&A[i]) ;
}
printf("You have input the List:\n") ;
for(i = 0 ;i < n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n") ;
RecurInsertSort(/*A,*/n) ;
printf("After Sort:\n") ;
for(i = 0 ; i < n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n\n") ;
}
return 0 ;
}
void RecurInsertSort(/*int A[],*/int n)
{
if(n > 0)
{
RecurInsertSort(/*A,*/n-1) ;
Insert(/*A,*/n-1,A[n-1]) ;
}
}
void Insert(/*int A[],*/int n,int nKey)
{
int i = n-1;
while(i >= 0 && A[i] > nKey)
{
A[i+1] = A[i] ;
i-- ;
}
A[i+1] = nKey ;
}
算法导论练习题2.3-6
不能,因为需要移动的元素数目仍然没变,所以最坏情况的时间复杂度还是O(n^2).
代码实现:
#include<stdio.h>
#define N 10
int A[N] ;
void BSearchInsert(/*A,*/int b,int e,int nKey) ;
int main(void)
{
int i,n,nKey ;
freopen("in.txt","r",stdin) ;
while(scanf("%d",&n) != EOF)
{
for(i = 0 ; i < n ; i++)
{
scanf("%d",&A[i]) ;
}
printf("You have input the List:\n") ;
for(i = 0 ; i < n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n") ;
for(i = 0 ; i < n ; i++)
{
nKey = A[i] ;
BSearchInsert(/*A,*/0,i-1,nKey) ;
}
printf("After Sort:\n") ;
for(i = 0 ; i < n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n\n") ;
}
return 0 ;
}
void BSearchInsert(/*A,*/int b,int e,int nKey)
{
int m = 0 ;
int nPos = 0 ;
int i = 0 ;
int n = e ;
if(A[n] <= nKey)
{
nPos = n+1 ;
}
else
{
while(b < e)
{
m = b + (e-b)/2 ;
if(A[m]>nKey)
{
e = m ;
}
else if(A[m]<=nKey)
{
nPos = m + 1 ;
b = m + 1 ;
}
}
i = n ;
while(i >= 0 && i >= nPos)
{
A[i+1] = A[i] ;
i-- ;
}
}
A[nPos] = nKey ;
}
算法导论练习题2.3-7
两种思路:
1、先用归并排序,再用折半查找,时间复杂度O(nlgn).
2、先用归并排序,再首尾元素相加,结果和x比较,如果比x大,尾指针指向前一个元素,如果比x小,就头指针指向下一个元素。时间复杂度也是O(nlgn),解法来自《编程之美》
解法一:
#include<stdio.h>
#include<string.h>
#define N 10
int A[N] ;
void Merge(/*A*/int p,int q,int r) ;
void MergeSort(/*A*/int p,int r) ;
int BSearch(/*A*/int b, int e,int v) ;
int main(void)
{
int i,n,nOther,x ;
int fFlag = 0 ;
freopen("in.txt","r",stdin) ;
while(scanf("%d%d",&n,&x) != EOF)
{
fFlag = 0 ;
for(i = 0 ; i < n ; i++)
{
scanf("%d",&A[i]) ;
}
printf("The x is %d ,Your have input the List:\n",x) ;
for(i = 0 ; i < n ; i++)
{
printf("%-3d",A[i]) ;
}
printf("\n") ;
MergeSort(0,n-1) ;
for(i = 0 ; i < n ; i++)
{
nOther = x - A[i] ;
if(BSearch(0,n,nOther) != -1)
{
fFlag = 1 ;
break ;
}
}
if(1 == fFlag)
{
printf("Find the combination : %d %d\n\n",A[i],nOther) ;
}
else
{
puts("Can't fine the combination.\n") ;
}
}
return 0 ;
}
void MergeSort(/*A*/int p,int r)
{
int q = 0 ;
if(p < r)
{
q = p + (r-p)/2 ; //notice
MergeSort(/*A*/p,q) ;
MergeSort(/*A*/q+1,r) ;
Merge(/*A*/p,q,r) ;
}
}
void Merge(/*A*/p,q,r)
{
int L[N], R[N] ;
int i,j,k ;
int nLeft,nRight ;
nLeft = q + 1 - p ; //notice
nRight = r - q ; //notice
for(i = 0 ; i < nLeft ; ++i )
{
L[i] = A[p+i] ;
}
for(j = 0 ; j < nRight ; ++j)
{
R[j] = A[q+j+1] ; //notice
}
i = 0 ;
j = 0 ;
for(k = p ; k < r && i<nLeft && j<nRight ; k++ )
{
if(L[i] <= R[j])
{
A[k] = L[i] ;
i++ ;
}
else
{
A[k] = R[j] ;
j++ ;
}
}
if(i >= nLeft)
{
for(; k <= r ; ++k,++j)
{
A[k] = R[j] ;
}
}
else
{
for(; k <= r ; ++k,++i)
{
A[k] = L[i] ;
}
}
}
int BSearch(/*A*/int b, int e,int v)
{
int m ;
while(b < e)
{
m = b + (e-b)/2 ;
if(A[m] == v)
{
return m ;
}
else if(A[m] > v)
{
e = m ;
}
else
{
b = m+1 ;
}
}
return -1 ;
}
解法二:
#include<stdio.h>
#include<string.h>
#define N 10
int A[N] ;
void Merge(/*A*/int p,int q,int r) ;
void MergeSort(/*A*/int p,int r) ;
int main(void)
{
int i,n,nOther,x ;
int fFlag = 0 ;
int b,e ;
freopen("in.txt","r",stdin) ;
while(scanf("%d%d",&n,&x) != EOF)
{
fFlag = 0 ;
for(i = 0 ; i < n ; i++)
{
scanf("%d",&A[i]) ;
}
printf("The x is %d ,Your have input the List:\n",x) ;
for(i = 0 ; i < n ; i++)
{
printf("%-3d",A[i]) ;
}
printf("\n") ;
MergeSort(0,n-1) ;
b = 0 ;
e = n-1 ;
while(b < e)
{
if(x == A[b] + A[e])
{
fFlag = 1 ;
break ;
}
else if(A[b] + A[e] > x)
{
e-- ;
}
else
{
b++ ;
}
}
if(1 == fFlag)
{
printf("Find the combination : %d %d\n\n",A[b],A[e]) ;
}
else
{
puts("Can't fine the combination.\n") ;
}
}
return 0 ;
}
void MergeSort(/*A*/int p,int r)
{
int q = 0 ;
if(p < r)
{
q = p + (r-p)/2 ; //notice
MergeSort(/*A*/p,q) ;
MergeSort(/*A*/q+1,r) ;
Merge(/*A*/p,q,r) ;
}
}
void Merge(/*A*/p,q,r)
{
int L[N], R[N] ;
int i,j,k ;
int nLeft,nRight ;
nLeft = q + 1 - p ; //notice
nRight = r - q ; //notice
for(i = 0 ; i < nLeft ; ++i )
{
L[i] = A[p+i] ;
}
for(j = 0 ; j < nRight ; ++j)
{
R[j] = A[q+j+1] ; //notice
}
i = 0 ;
j = 0 ;
for(k = p ; k < r && i<nLeft && j<nRight ; k++ )
{
if(L[i] <= R[j])
{
A[k] = L[i] ;
i++ ;
}
else
{
A[k] = R[j] ;
j++ ;
}
}
if(i >= nLeft)
{
for(; k <= r ; ++k,++j)
{
A[k] = R[j] ;
}
}
else
{
for(; k <= r ; ++k,++i)
{
A[k] = L[i] ;
}
}
}