插入排序自己遇到过的一些坑

哎,说到底还是很伤心的,最简单的直接插入排序我都写不好,555…
今天夜晚写了一个错的插入排序,觉得有必要记录下来

void insertsort(int arr[],int n)
{
	int i,j;
	for(i = 1;i<n;i++)
	{
		int e = arr[i];   //为当前要插入元素保存副本
		for(j = i-1;j >= 0 ;j--)  //与i的前一个来对比(注意这里循环结束的条件)
		//这里循环结束的条件是j < 0 ,这里一个书写不是很好的是j可以取得值-1,但是并不是错误
		{
			if(arr[j] > e)
			{
				arr[j+1] = arr[j];
			}

		}
	
	    arr[j+1] = e;	

	}
}

这个程序的思想是:先给每一次要比较的元素创建一个副本,然后当需要交换顺序的时候,并不交换,而是通过赋值操作,这样来减少时间复杂度。

❗️这个程序是错误的

这里先介绍一下c语言中for循环的语法

for ( init; condition; increment )
{
   statement(s);
}

下面是 for 循环的控制流:

1.init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。
2.接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。(这一句是重点了)
3.在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。
4.条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。

上面那个程序的错误就出在那个for循环中,我们再来看一下代码:

for(i = 1;i<n;i++)
	{
		int e = arr[i];   //为当前要插入元素保存副本
		for(j = i-1;j >= 0 ;j--)  //与i的前一个来对比(注意这里循环结束的条件)
		//这里循环结束的条件是j < 0 
		{
			if(arr[j] > e)
			{
				arr[j+1] = arr[j];
			}

		}	
	    arr[j+1] = e;	
	}

这里的for循环写的是,只要j是大于等于0的我们就可以往下执行,所以,到最后,只有j = -1的时候才会跳出循环,而arr[j+1] = e;这一句赋值操作永远都赋给了arr[0]了。
所以只要我们将代码改动一小部分,就可以完成我们的插入排序了

void insertsort(int arr[],int n)
{
	int i,j;
	for(i = 1;i<n;i++)
	{
		int e = arr[i];//所以这样写错误的
		for(j = i-1;j >= 0 && arr[j] > e ;j--) //这里的循环条件变成了两个
		{
			//if(arr[j] > e)
			//{
				arr[j+1] = arr[j];
			//}

		}
		//原来死在这里,这里每一次都是不满足条件后才执行,所以都赋值给1了?	
	    arr[j+1] = e;	

	    printArray(arr,n);
	}
}

这里for循环执行下去的条件多了一个 arr[j] > e,这样也就是说只有前一个元素比e大的时候,才会继续执行j--操作。由于j的位置即为插入的位置,所以,此时我们就正确的找到了插入的位置~

2.带哨兵的插入排序法

哎,严奶奶的伪代码真的只适合聪明的人看。像我这样的渣渣,浪费了一个自习,还是颗粒无收,所以,今 天 一定要弄明白!!!

使用a[0]作为哨兵

for(i = 2;i < n; i++)
	{
		if(arr[i-1] > arr[i])
		{
			arr[0] = arr[i];
			arr[i] = arr[i-1];

			for(j = i -2 ; arr[j] > arr[0];j--)  //这里最低在j = 0的时候也退出了
			{
				arr[j+1] = arr[j];

			}

			arr[j+1] = arr[0];
		}
   }

习题10.23答案:

	void insertsort(int arr[],int n)
  {
	int i,j;
    for(i = n-3;i >= 0; i--) 
	{
		if( arr[i] > arr[i+1] )
		{
			arr[n-1] = arr[i];
			arr[i] = arr[i+1];

			for( j = i + 2; (arr[j] < arr[n-1]); j++)
				arr[j-1] = arr[j];

			arr[j-1] = arr[n-1];

		}
	}

猜你喜欢

转载自blog.csdn.net/qq_37414405/article/details/88784097