插入排序及归并排序(附C++代码)

插入排序及归并排序(附C++代码)

该算法对于少量元素的排序是一个有效的算法。
伪代码(写代码时可以参照):

INSERTION-SORT(A)
for  j=1 to A.length
	key=A[j]
	i=j-1
	while i>=0 and A[i]>key
		A[i+1]=A[i]
		i++
	A[i+1]=key

对插入排序算法的分析:

假定:
第i行的每次执行时间ci
tj表示对j第4行执行while循环测试的次数
n=A.length
m 1 m_1 m1= ∑ j = 2 n t j \displaystyle\sum_{j=2}^{n}t_j j=2ntj
m 2 m_2 m2= ∑ j = 2 n ( t j − 1 ) \displaystyle\sum_{j=2}^{n}(t_j-1) j=2n(tj1)

INSERTION-SORT(A)                                  代价                           次数
for  j=1 to A.length	                             c1                             n
	key=A[j]                                     c2				    n-1
 	i=j-1                                        c3                             n-1
 	while i>=0 and A[i]>key                      c4                             m1
 		 A[i+1]=A[i]                         c5                             m2
  		 i++                                 c6                             m2
	 A[i+1]=key				     c7                             n-1
运行时间

T n T_n Tn= c 1 c_1 c1n+ c 2 c_2 c2(n-1)+ c 3 c_3 c3(n-1)+ c 4 c_4 c4 ∑ j = 2 n t j \displaystyle\sum_{j=2}^{n}t_j j=2ntj+ c 5 c_5 c5 ∑ j = 2 n ( t j − 1 ) \displaystyle\sum_{j=2}^{n}(t_j-1) j=2n(tj1)+ c 6 c_6 c6 ∑ j = 2 n ( t j − 1 ) \displaystyle\sum_{j=2}^{n}(t_j-1) j=2n(tj1)+ c 7 c_7 c7(n-1)
若输入的数是已排好的数,为最佳情况,此时 t j t_j tj =1
T n T_n Tn= c 1 c_1 c1n+ c 2 c_2 c2(n-1)+ c 3 c_3 c3(n-1)+ c 4 c_4 c4(n-1)+ c 7 c_7 c7(n-1)
=( c 1 c_1 c1+ c 2 c_2 c2+ c 3 c_3 c3+ c 4 c_4 c4+ c 7 c_7 c7)n-( c 2 c_2 c2+ c 3 c_3 c3+ c 4 c_4 c4+ c 7 c_7 c7)
可以看为 an+b
若输入数组为反向排序,为最坏情况,此时 t j t_j tj =j
T n T_n Tn= c 1 c_1 c1n+ c 2 c_2 c2(n-1)+ c 3 c_3 c3(n-1)+ c 4 c_4 c4(n(n-1)/2-1)+ c 5 c_5 c5n(n-1)/2+ c 6 c_6 c6n(n-1)/2+ c 7 c_7 c7(n-1)
=( c 4 c_4 c4/2+ c 5 c_5 c5/2+ c 6 c_6 c6/2) n 2 n^2 n2+( c 1 c_1 c1+ c 2 c_2 c2+ c 3 c_3 c3- c 4 c_4 c4/2- c 5 c_5 c5/2- c 6 c_6 c6/2+ c 7 c_7 c7)n-( c 2 c_2 c2+ c 3 c_3 c3+ c 4 c_4 c4+ c 7 c_7 c7)
可以看为 a n 2 n^2 n2+bn+c

我们集中于最坏情况运行时间,因为最坏运行时间为运行时间的一个上界,在某些算法里最坏情况经常出现,“平均情况”往往与最坏情况大致一样。
对于a n 2 n^2 n2+bn+c,当n很大时,我们忽略低阶项最重要项常系数,故可化为 n 2 n^2 n2

设计算法

分治法

伪代码

MERGE<A,p,q,r>
n1=q-p+1
n2=r-q      
for i=1 to n1
	L[i]=A[p+i-1]
for j=1 to n2
	R[j]=A[q+j]            //将数组分为L[1...n1+1]和R[1...n2+1]两个数组,假设这两个数组都是已排好序的
L[n1+1]=
R[n2+1]=                       //设置哨兵牌,来知道是否有数组到末尾,如果到了直接将另一组数全部放到新数组中
i=1
j=1
for k=p to r
	if L[i]<=R[j]
		A[k]=L[i]
		i++
	else A[k]=R[j]
		j++	

运行时间为n, n=r-p+1.
上面那段伪代码是假设分成了已经排好序的两段代码,而事实大多数不会如此。
所以现在把MERGE作为归并排序的子程序使用,将A[p…r]分成两个子数组A[p…q]和A[q+1…r],前者包含大于等于n/2最小整数个元素,后者包含小于等于n/2最大整数个元素,这样一直分下去直到分为含有小于等于两个元素的数组。当为两个元素时再用MEGER函数将两个元素排好序作为再次使用MEGER的两个排好序的数组中的一个再次进行MEGER,如此继续重复上面步骤知道将原数组分成两个已排好序的数组,最后再用这两个数组进行MEGER得到排好序的原数组。

下面举个例子

对于A=[3,41,52,26,38,57,9,49]
在这里插入图片描述
这是对数组分为两组后得到未排序的两组数组进行排序的伪代码:

MERGE-SORT(A,p,r)
if p<r
	q=[(p+r)/2]               //小于等于(p+r)/2 的最大整数
	MERGE-SORT(A,p,q)
	MERGE-SORT(A,q+1,r)
	MERGE(A,p,q,r)

插入排序法代码(C++)

#include<iostream>
using namespace std
int main(){
int A[8]={3,41,52,26,38,57,9,49};
for(int j=1;j<8;j++){
	int key=A[j];
	int i=j-1;
	while((i>=0)&&(A[i]>key)){
		A[i+1]=A[i];
		i--;
		}
	A[i+1]=key;
	}
for(int i=0;i<8;i++){
	cout<<A[i]<<" ";	
	}
	cout<<endl;
	system("pause");
}

在这里插入图片描述

归并排序法代码(C++)

#include<iostream>
using namespace std;
void MERGE(int A[],int p,int q,int r);
void MERGESORT(int A[],int p,int r);
int main(){
	int A[8]={3,41,52,26,38,57,9,49};
	MERGESORT(A,0,8);
	for(int i=0;i<8;i++){
		cout<<A[i]<<" ";
	}
	cout<<endl;
	system("pause");
}
void MERGE(int A[],int p,int q,int r){
	int mid=q;
	int left=p;
	int B[8];       //这里B作为临时数组,建议用指针。
	for(int k=p;k<r;k++){
		if((p<mid)&&(q<r)){                    //对两组数进行比较较小的放入暂时数组
			if(A[p]<=A[q]){
				B[k]=A[p];
				p++;
			}
			else{
				B[k]=A[q];
				q++;
			}
		}
		else{                               //下面是检测是否有一组数到了末尾
			if((p<mid)&&(q>=r)){
				B[k]=A[p];
				p++;
			}
			if((p>=mid)&&(q<r)){
				B[k]=A[q];
				q++;
			}
		}
	}
	p=left;
	for(int i=0;i<r;i++){
		A[i]=B[i];
	}
}
void MERGESORT(int A[],int p,int r){
	if(p<(r-1)){
		int q=(p+r)/2;
		MERGESORT(A,p,q);
		MERGESORT(A,q,r);
		MERGE(A,p,q,r);
	}	
}

结果同上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值