菜鸡笔记之——插入排序
插入排序可分为:直接插入排序、折半插入排序
一、直接插入排序
时间复杂度为O(n^2)
思路(以从小到大排序为例):
1、给定一组数据,只看第一个元素,认为已经排好序;(一个数可以看成排 好序,这没的说)
2、看a[0]与a[1]的大小关系,并把a[1]赋给临时变量temp,如果a[0]大于a[1],将a[0]的值赋给a[1](相当于把a[0]往右挪一个位置),然后把temp插入到第一个位置,否则不动;
3、看第i个数与第前面已排序的各个数的大小关系,并把第i个数赋给临时变量temp,把比a[i]大的数都往后挪一个位置,然后把temp插入到空出来的位置;
4、重复3,直到遍历完整组数据
# include <stdio.h>
# include <malloc.h>
int main(void)
{
int N,i,flag,temp;
printf("the number of the list:");
scanf("%d",&N);
int * list = NULL;
list = (int *)malloc(sizeof(int)*N); //动态分配内存
if (list==NULL)
{
printf("error!\n");
exit(-1);
}
for (i = 0;i<N;i++) //输入数据
{
scanf("%d",list+i);
}
//排序
for (i = 1;i<N;i++)
{
temp = *(list+i); //将当前数值记住
flag = i-1;
while ((flag>=0)&&(*(list+flag)>temp)) //从*(list+flag)开始,从右往左,把比temp
{ //大的元素向右挪一位,直到*(list+flag)<=temp为止
*(list+flag+1) = *(list+flag);
flag--;
}
*(list+flag+1) = temp; //将temp插入
}
for (i = 0;i<N;i++) //输出已排序数据
{
printf("%3d",*(list+i));
}
free(list);
return 0;
}
(👆用动态内存分配决定数组大小)
二、折半插入排序
时间复杂度为O(n^2)
思路:
插入排序分为直接插入与折半插入,折半插入与直接插入相比,只是在查找插入位置时方法优化了而已,直接插入在查找插入位置时是逐次比较,直到遇到第一个比他小(大)的数后插入,折半插入查找插入位置时类似于二分查找
# include <stdio.h>
# include <malloc.h>
int main(void)
{
int N,i,j,key;
printf("the number of the list:");
scanf("%d",&N);
int * list = NULL;
list = (int *)malloc(sizeof(int)*N);
if (list==NULL)
{
printf("error!\n");
exit(-1);
}
//输入
for (i = 0;i<N;i++)
{
scanf("%d",list+i);
}
//排序
for (i = 1;i<N;i++)
{
int low = 0;
int high = i-1;
int mid;
key = *(list+i);
while (low<=high) //折半查找插入位置
{
mid = (low+high)/2;
if (*(list+mid)>key)
{
high = mid-1;
}
else
{
low = mid+1;
}
}
for (j = i;j>low;j--) //将插入位置到list+i-1位置上的数往后挪一格
{
*(list+j) = *(list+j-1);
}
*(list+low) = key; //把*(list+i)填到空出来的位置
}
//输出
for (i = 0;i<N;i++)
{
printf("%3d",*(list+i));
}
free(list);
return 0;
}
(👆用动态内存分配决定数组大小)
while (low<=high) //折半查找插入位置
{
mid = (low+high)/2;
if (*(list+mid)>key)
{
high = mid-1;
}
else
{
low = mid+1;
}
}
上面这一段最终想得到的是low的值(要插入的位置),比如
如果前面已排好序的一串数为:1,3 ,5,7,9
接下来的一个数(也就是key)的值为4,则low = 2,[key = 3时,low也是2,即插入的位置是遇到的第一个比key大/小的数的位置]。