直接插入算法入门

插入算法的简单介绍,本人也是个小白。写在这里既是加深自己的理解,也希望能帮助一下那些想要认识该算法的朋友。由于本人也是多从网上学来,如内容有雷同之处,请勿见怪。再次声明本文仅作学习交流。

1.      插入算法。

插入算法其实说白了,就是一个操作---比较。比较的对象则是需要排序的元素和已经排好的序列。

比如数组a[0,…,i-1]和a[i]比较。a[0,…,i-1]就被认为已经排好序了,a[i]是待排元素。如果a[i]大于a[i-1],自然a[i]大于a[0,…,i-1]中每一个元素。不需要进行任何操作。只需要开始下一轮比较-----将i后移。也就是继续取数组下一个元素和a[0,…,i]比较。如果a[i]小于a[i-1]则继续向前比较直到找到a[0,…,i-1]中大于a[i]的元素或者下标为0处(前面数字都比较完了也没找到,那么a[i]应该是前i个元素中最小的)。然后将该元素之后的所有元素(一直到i-1)这个位置后移一位,将a[i]插入到该元素后面。这样数组前i个元素就都有序了。接着开始下一轮的比较。

 插入算法的开始是默认数组第一个元素就是有序的,所以比较从下标1开始,一直到n-1,总共需要比较n-1次。

 列表说明插入算法的过程。

0

1

2

3

4

5

6

7

8

3

4

1

3

4

5

1

8

7

                                       注:第一行为数组下标,第二行为对应元素

 

第一次比较:默认下标为0的序列有序,则a[1]和a[0]比较。4>3,不予操作。此时数组可以看到前两个数有序。即a[0]<a[1];下面将取第三个元素和数组前两个进行比较。

0

1

2

3

4

5

6

7

8

3

4

1

3

4

5

1

8

7

           这里用红色表示前面提到的有序数组a[0,…,i-1]

第二次比较。取a[2]和a[1]比较,a[2]<a[1],则继续向前比较a[2]<a[0],此时已经比较完了,a[2]最小,比较终止的位置下标元素全部后移。最后将a[2]放到比较终止位置上,本次比较结束。

0

1

2

3

4

5

6

7

8

2

3

4

3

4

5

1

8

7

如此下去,一共需要比较n-1次。

代码如下:

public static void insert_sort(int a[], int n){    //这里因为是直接被静态方法main()调用,所有声明为static.参数a 为数组,n为数组长度。
	   int i,j,k;
	   for(i=1;i<n;i++){      //i从1开始进行比较,共需要比较n-1次。这里强掉一下:你只有比较到最后一个元素才知道究竟第一个元素是不是全局最小。
		   for(j=i-1;j>=0;j--){    //下标为i的元素和它之前的元素逐次比较
			   if(a[i]>a[j])   //找到比a[i]大的已排好序列中的位置即插入位置j+1
				   break;
		   }
		   int value=a[i];   //防止在接下来的后移中a[i]被覆盖丢失。
		   for(k=i-1;k>j;k--){  //j到i之间元素逐次后移一位,不包括下标为j的那个。
			   a[k+1]=a[k];
		   }
		   a[k+1]=value;//将a[i]放到第j+1个位置。此时K==j的。
	   }
 上述代码是先找到插入位置,然后后移元素。也可以用一个for循环完成。如下:

public static void insert_sort(int a[],int n){             
           int i,j;
	   for(i=1;i<n;i++){
		   int temp=a[i];
		   for(j=i-1;j>=0&&a[j]>temp;j--) //只要a[j]大于temp就移位。<span style="font-family: Arial, Helvetica, sans-serif;">注意j>=0这个条件要放在前面,因为j--时可能出现j=-1的情况</span><pre name="code" class="java">                                                        //根据for循环的情况,如果你把a[j]>a[j+1]放在j>0前面,将会报错数组下标出现-1的情况。
a[j+1]=a[j]; a[j+1]=temp;//最后插入}

 

上面也是在最后执行的插入操作,说白了也是先找到位置,边找边移位。其实也可以边找位置边执行位置交换。即只要a[i]<a[j]二者就交换位置。这样就省掉了最后的插入操作。代码如下:
public static void insert_sort(int a[],int n){
        int i,j;
	   for(i=1;i<n;i++){
		   for(j=i-1;j>=0&&a[j]>a[j+1];j--){ //这里是两两比较,每比较一次交换一次。直到a[i]>a[j].注意j>=0这个条件要放在前面,因为j--时可能出现j=-1的情况
                                                        //根据for循环的情况,如果你把a[j]>a[j+1]放在j>0前面,将会报错数组下标出现-1的情况。
			   temp=a[j+1];
			   a[j+1]=a[j];
			   a[j]=temp;
		   }
	   }

 

插入排序最坏的情况是原数组与你想排的正好相反。如你想从小到大,可实际待排数组正好从大到小。每次比较都需要移动所有排好数组元素的位置。O(n2),最好的是已经有序O(n)。平均情况是O(n2).从代码也可以看出时间复杂度上有两个for循环。再次强调插入排序只有在结束才能确定最终的最大最小值。因为每次比较排序都只是针对钱i个元素。

读者还有不懂可以参阅http://blog.csdn.net/morewindows/article/details/6665714。本文主要代码也是参阅与此。本文仅作交流,若有不当,敬请留言。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值