插入排序

插入排序的思想:

        每趟将一条待排序的记录,按其关键字值的大小插入到前面已经排好序的记录中的适当位置,直到全部记录插入完成排好序为止。直接插入排序的基本要求是,假设待排序的记录存放在r[0,1....n-1]中,开始时先将第0个记录组成一个有序的子序列,然后依次将后面的记录插入到前面排好序的子序列中,并且一直保持子表的有序性。

   假设一组待排序的记录关键字序列为 {39,67,95,70,8,25,52},插入的全过程如下:

                          i=1     39,67,95,70,8,25,52      // 67跟前面排好序的元素对比,如果前面一个元素比当前元素大。前面一个元素往后移一位

  i=2     39,67,95,70,8,25,52

  i=3     39,67,70,95,8,25,52

  i=4     8,39,67,70,95,25,52

  i=5     8,25,39,67,70,95,52

  i=6     8,25,39,52,67,70,95


  直接插入排序算法的主要步骤:

  (1) 将r[i]暂存放在临时变量 temp中。

  (2)将temp与r[j](j=i-1,i-2.....,0)一次比较,若r[j] > temp 则将r[j]往后移一位置,直到r[j]<temp时,r[j+1]即为插入位置处。

  (3)将temp插入到r[j+1]处。

  (4)令i=1,2,3.......n-1,重复上面步骤,直到全部序列排好序。


算法代码:

public void innersort(int[] arr, int len) {
		int temp;
		int i, j;
		for (i = 1; i < len; i++) { // n-1趟扫描
			temp = arr[i]; // 将待插入的第i条记录暂存放在temp中
			for (j = i - 1; j >= 0 && temp < arr[j]; j--) {
				arr[j + 1] = arr[j]; // 如果比前面的数小,则将前一个数往后移动一位
			}
			arr[j + 1] = temp; // 找到插入位置后插入数字
		}
	}


二分法插入排序代码:

	// 二分插入排序

	public void insertsort(int[] sort, int n) {
		if (sort == null || n <= 1) {
			return;
		}
		int temp = 0;
		int left = 0;
		int right = 0;
		int middle = 0;
		for (int i = 1; i < n; i++) {
			temp = sort[i];
			left = 0;
			right = n - 1;
			while (left <= right) {
				middle = (left + right) / 2;
				if (sort[middle] > temp) {
					right = middle - 1;
				} else {
					left = middle + 1;
				}
			}    //找到到插入位置left

			for (int j = i - 1; j >= left; j--) {
				sort[j + 1] = sort[j];
			}

			sort[left] = temp;
		}
	}


带监视哨的之间插入排序算法代码:

public static void insertsort(int[] sort,int len){
		if(sort == null || len < 1)
			return ;
		int i,j;
		for(i=1;i<len;i++){
			sort[0] = sort[i];//sort[0]作为监视哨,那么正常的记录只能存放在下标从1到n-1的存储单元中,即具有n个存储单元的顺序表只能存储n-1个记录。
			for(j=i-1;sort[j]>sort[0];j--){
				sort[j+1] = sort[j];
			}
			sort[j+1] = sort[0];
		}
	}


算法性能分析:

    空间复杂度:仅用了一个辅助单元,空间复杂度为O(1)

    时间复杂度:从时间性能上看,逐个插入记录的操作进行了n-1趟,每趟操作分为关键字的比较和移动记录,而比较的次数和移动记录的次数取决于待排序列关键字初始排列状态。最好情况下是待排序列按关键字有序排列,对于不带监视哨排序算法,没有移动记录操作,带监视哨算法的移动次数为 2(n-1)次,比较次数均为n-1次;最坏情况是待排序列按照关键字逆序排列,每趟排序都要将待插入的数插入到前面排好序记录表的最前面位置,为此,第i趟插入需要需要进行关键字比较的次数为i次,移动记录的次数为i+2次,总的比较次数为1/2*n(n-1),总的移动次数为 1/2*(n*n+3n-4);一般情况下,待排序记录出现的概率相同,第i趟排序所需的比较和移动次数可取上述最小值与最大值的平均值,约为i/2,总的平均比较和移动次数均为n*n/4,因此,之间插入排序的时间复杂度为O(n*n);

   算法稳定性:排序前后元素的相对位置没有发生变化,因此是稳定的排序算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值