算法导论第2章(1):插入排序,算法分析

排序基类

public abstract class Sort
{
	public static final int  INCREMENT = 0; //升序
	public static final int  DECREMENT = 0; //降序
	
	/**
	 * 排序过程
	 * @param s 带排数列
	 * @param incOrDec 控制升序还是降序
	 * @return
	 */
	public int [] sort(int [] s, int incOrDec){return null;};
	
	/**
	 * 打印 一个数列
	 * @param s
	 */
	public void print(int [] s)
	{
		if(s == null) { System.out.println("s == null"); return; }
		for(int i:s)
			System.out.print(i +" ");
	}
}


 

插入排序 insert-sort

对数列A进行排序

伪代码:

1

for j <- 2 to  length(A)

2

    do key <-A[j]

3

    // A[j]插入到已经排好序的数列A[1...j-1]

4

    i <- j-1;

5

    //已经排好序的数列A[1...j-1]中中,找到第一个比key小的元素的位置

6

    while i>0 and A[i] > key

7

        do A[i+1]<-A[i]

8

        i <- i-1

9

    A[i+1] = key;

 

下面是一个例子的排序过程:

 

java 实现插入排序

 

/**
 * 
 * @author buptjunjun
 * @time 2013-1-22
 *
 */
public class InsertSort extends Sort
{	
	/**
	 * 插入排序
	 * @param s 带排数列
	 * @param incOrDec 控制升序还是降序
	 * @return
	 */
	@Override
	 public int[] sort(int[] s,int incOrDec)
	 {
		if(s == null || s.length <=1) return s;	
		for(int i = 1;i <s.length; i++)
		{
			int key = s[i];
			int j = i-1;
			//下面将key插入到已经排好的数列中去
			if(incOrDec == Sort.INCREMENT) //升序
			{	
				while(j>=0 && key<s[j]){ s[j+1] = s[j]; j--;}
			}
			else if(incOrDec == Sort.DECREMENT) //降序
			{
				while(j>=0 && key>s[j]){ s[j+1] = s[j]; j--;}
			}
			s[j+1] = key;
		}		
		return s;
	}
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		int [] s = {2,5,3,1,1,3,4,4,9,0};
		int [] ret = new InsertSort().sort(s,Sort.INCREMENT);		
		new InsertSort().print(s);
	}

}


如何证明算法是正确的(归纳法)

要证明一个算法是正确的,分2步:

1、在第一轮迭代之前是正确的

2、在循环的某一次迭代开始之前是正确的,在下一次开始之前是正确的。

其实这就是一个数学归纳法的应用

 

算法分析

Num

算法

Cost

T

1

for j <- 2 to  length(A)

C1

n

2

    do key <-A[j]

C2

n-1

3

    // A[j]插入到已经排好序的数列A[1...j-1]

0

n-1

4

    i <- j-1;

C3

n-1

5

    //已经排好序的数列A[1...j-1]中中,找到第一个比key小的元素的位置

0

n-1

6

    while i>0 and A[i] > key

C4

 

7

        do A[i+1]<-A[i]

C5

8

        i <- i-1

C6

9

    A[i+1] = key;

C7

n-1

 

其中Ci是第j个语句的所用时间,Tjj个语句执行的次数

 

总时间就是:

T = n*C1 + (n-1)*C2+ (n-1)*C3+ ()*C4 + () *C5+ () *C6+(n-1)*C7

现在要确定的是t

当数组已经是排好序的那么tj= 1

T = n*C1 + (n-1)*C2+ (n-1)*C3+ (n-1)*C4+ +(n-1)*C7

  = (C1+C2+C3+C4+C7)n -(C2+C3+C4+C7) = a*n+b

 

可见当值排好序的情况下 Tn的线性函数

 

当数组已经是按逆序排好序的那么tj= j

 = n*C1 + (n-1)*C2+ (n-1)*C3+ ()*C4 + () *C5+ () *C6+(n-1)*C7

=a*n2+b*n+c

可见 T是关于n的二次函数

 

函数增长量级:

在前面分析中,我们忽略了每条语句的真实代价,使用a b c来代替,他们是依赖于Cj的。可以再做抽象,我们取最高次项,忽略了低次项目,因为当n很大的时候低次项是不重要的。

可以进一步抽象去掉最高次项的系数,因为因为当n很大的时候,系数对增长率的贡献很小。

这样可以这样表示插入排序的最坏时间代价为

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值