-
学习笔记
首先,我们先理解“栈”的概念
栈,即 stack,有点类似于货箱,为什么这么说呢?请看下图:
它的存取方式完全是货箱的存储方法:LIFO ( Last In First Out )后进先出法;
就了解这么多,我们可以步入正题:Insertion Soct( 插入排序 )
插入排序,就好像打扑克牌;开始的时候,左手是空的,右手抓牌;我们抓到第2张的时候,右手就开始插入;所以无论什么时候左手的牌总是有序的。
图中:S代表有序的序列,R则代表无序的序列,阴影部分则是需要插入的一个数,这便是一次插入。关于S的变化是往后移动了一格;开了一个偷、头,我们只要重复该步骤,就可以将R全部插入至S中,完成排序。
而,阴影部分移动的过程,就需要用到“栈”了。我们要将高于阴影部分的S一个一个拿出来,再将S放进去,最后将拿出来的都放进去。
关于插入排序的动态图可以去这个网址:http://www.atool.org/sort.ph
代码如下
-
核心代码:
void Insertion_Sort(int Array[],int n)
{
int i,j;
for(i =1; i <n; i++)
{
int temp=Array[i];
for ( j =i; j >0 && Array[j-1] >temp; --j)
Array[j]=Array[j-1];
a[j]=temp;
}
}
-
具体样例:
#include <stdio.h>
void Insertion_Sort(int Array[],int n)
{
int i,j;
for(i =1; i <n; i++)
{
int temp=Array[i];
for ( j =i; j >0 && Array[j-1] >temp; --j)
Array[j]=Array[j-1];
Array[j]=temp;
}
}
int main()
{
int Array[]={9,4,7,1,6,2,8,3,5};
int n=sizeof(Array)/sizeof(int),i;
Insertion_Sort( Array,n );
for ( i=0; i <n; i++)
{
printf("%d ",Array[i]);
}
return 0;
}
-
运行截图:
-
问题思索:
插入排序是需要一个转存通道的;就像抓牌,右手就是一个转存通道;那么请问:
(1)样例中数组,转存的次数是多少?
(2)一组未知的无序数组(假设有n个数),转存的次数最大值,最小值是多少?
-
关于问题:
我们先考虑数组{3,2,1},3移动至左手,次数0+1;2移动至右手,3移动至牌堆顶,2移动至左手,次数0+1+1;3移动至右手,再移动至左手,次数0+1+1+1;1移动至右手,3移动至牌堆顶部,再2移动至牌堆顶部,次数0+1+1+1+1;2移动右手再左手,次数0+1+1+1+1+1;3移动至右手再左手,次数0+1+1+1+1+1+1=6。
通过上面这个简单的例子;可以发现,转存的次数,与数组里的数组的逆序对有关;数组{3,2,1}有三个逆序对 (3,2)(3,1)(2,1),三个逆序对,而有序数组{1,2,3}也需要转存3次;所以不难推测出
(转存次数)=(数的个数)+(逆序对数)
我们就先解决了问题(2)
最小值对应有序数组 ——即 n
最大值对应逆序数组——即 n+n-1+n-2+.....+1=n(n+1)/2
那么相对应的第一问也出来了,逆序对有19对,转存次数为28个。