插入排序

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] ;
		}
	}
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值