插入排序(直接插入排序)

排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

直接插入排序

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列 。其实这就类似我们玩扑克牌,我们手上已经接的牌已经给它排好了序,当我们再接一张的时候要把它一个个比较按照相应的顺序插入到合适的位置。
那直接插入排序具体怎么做的呢?
当插入第 i(i>=1) 个元素时,前面的 array[0],array[1],…,array[i-1] 已经排好序,此时用 array[i] 的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将 array[i] 插入,原来位置上的元素顺序后移。

实现

下面我们一步步来实现它
首先让所有数都放在数组a里面,我们定义一个end位置,让它表示第end位置是已经拍好拍好序的最后一个位置,如果end=0就表示已经插入了一个数,因为只有这一个数,所以它肯定是有序的;定义一个tmp表示接下来要插入的数,即tmp=a[end+1];
#include<stdio.h>
void InsertSort(int* a, int n)//直接插入排序
{
  int i=0;
  int end=i;
  int tmp=a[end+1];
  
}

接下来我们就要插入数据,即就要比较a[end]和tmp谁小,谁小谁放在前面(假设我们都是按照升序排)。前一个位置比较谁大谁小,

如果a[end]>tmp的话,那tmp就要往前挪,a[end]就要往后挪一个位置;即a[end+1]=a[end];此时不能直接让a[end]=tmp,这个时候end--,继续跟前一个位置比较谁大谁小


  if(a[end]>tmp)
  {
     a[end+1]=a[end];
     end--;
  }

接下来我们走else情况,即a[end]<=tmp,tmp都已经大于已经拍好的序列的最后一个位置了,那肯定比这个序列的所有数都大。这个时候我们只需要把tmp赋给end+1位置就好了,但是我们可以不在这个添加这个语句,我们直接用break跳出else,我们在等tmp一遍遍走完if条件,最后一次走玩else的时候在最后添加这个语句,当a[end]>tmp一次次让end--,指定end=0的时候a[end]还是大于tmp,end--=-1,那就证明tmp是最小的,那就可以在while循环后面加a[end+1]=tmp。让新的a[0]=tmp。

while (end >= 0)
{
	if (a[end] > tmp)
	{
		a[end + 1] = a[end];
		end--;
	}
	else
	{
		break;
	}

}
a[end + 1] = tmp;

走到这里,这就相当插入一个数走完了,那还有n-2个数还有插入(因为第一个数自动有序不用插入,一般从第二个数插入)。所以我们外面再套一层循环

for(i=0;i<n-1;i++)
{
   ....
}

为什么是i<n-1呢?因为i是从0开始,而我们是从a[1]开始插入数据的。

测试

#include<stdio.h>
int main()
{
	
	int a[] = { 6,1,2,7,9,3,4,5,10,8 };
	int n = sizeof(a) / sizeof(a[0]);
	InsertSort(a, n);
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

这个排序到这里也就写完了。

时间复杂度

这个排序的时间复杂度是多少呢?插入一个数,需要最坏情况下需要挪动多少次?肯定就是从end+1位置挪动到0位置,一共需要插入n-1个数,所以直接插入排序的时间复杂度是O(N^2)。

源代码

​
void InsertSort(int* a, int n)//直接插入排序
{
	for (int i = 0; i < n-1; i++)
	{
		int end = i;
		int tmp = a[end+1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}

		}
		a[end + 1] = tmp;
	}
}

​

猜你喜欢

转载自blog.csdn.net/weixin_67131528/article/details/135042270