上篇文章已经提到直接插入排序中,时间消耗在了元素间的比较次数和移动这两方面。折半插入排序可以减小比较次数,而表插入排序则可以避免元素移动。但它需要建立数据结构,并且需要额外的空间(省时一般都耗空间,这个在算法上很常见哦!)。
首先给出表结构,定义如下:
#define SIZE 100
typedef struct
{
int value;
int next;
}SLNode;
typedef struct
{
SLNode numbers[SIZE];
int length;
}SLinkList;
其实,表结构就是一个静态链表,它可以用一个数组来初始化,初始化用头元素和第一个元素组成一个循环链表,然后排序时从第二个元素开始插入到这个循环链表中,当然只是修改每个元素的next域。使头结点的next域始终指示最小的那个元素,然后依次向下:每一个元素的next域都指示比它稍大的那个元素。最大的元素的next域指示头结点。这样形成一个循环链表。
当记录下这些信息后,最后一步就是按照next域的指示调整表结构中数组,得到最后的排序结构。下面分三步给出具体的代码:
1、用数组初始化表结构。
2、修改next域形成有序的循环链表。
3、根据next域信息调整表结构中的数组,是数据从小到大排列。
最后再给出一个flash演示,因为文章中不能插入.swf格式的文件,所以我给出链接和文件下载地址。这个动画演示了表插入排序的整个过程。
一:用数组初始化表结构,代码如下:
//参数含义:
//values:存储数据的整形数组
//count: 数组的大小
int InitLink(SLinkList* linkList,int* values,int count)
{
if(count>=SIZE)
{
printf("超出范围!\n");
return 0;
}
//头节点指示第一个元素,并赋予整形最大值(当然只要赋一个比你要排序的数都大的值就行了)
linkList->numbers[0].value = INT_MAX;
linkList->numbers[0].next = 1;
for(int i=1;i<=count;i++)
{
linkList->numbers[i].value = values[i-1];
linkList->numbers[i].next = 0;
}
linkList->length = count+1;
return 1;
}
初始化后结构图如下:
( 其中要排序的数组为:int values[LENGTH] = {68,45,23,37,54,12,81,76}; LENGTH 为宏定义是整数 8)
二、修改next域形成有序的循环链表。代码如下:
int Sort(SLinkList* linkList)
{
int len = linkList->length;
for(int i=2;i<len;i++)
{
int q=0;
int p = linkList->numbers[0].next;
while( linkList->numbers[i].value > linkList->numbers[p].value )
{
q = p;
p = linkList->numbers[p].next;
}
linkList->numbers[q].next = i;
linkList->numbers[i].next = p;
}
return 1;
}
修改next域后如图所示:
每一个元素的next域都指示下一个比它稍大的元素。
三、根据next域调整数组,使数组有序。代码如下:
// 根据静态链表linkList中各结点的指针值调整记录位置,使得linkList中记录按关键字非递减有序顺序排列
void Arrange(SLinkList* linkList)
{
SLNode temp;
int i,p,q;
// p指示第一个记录的当前位置
p = linkList->numbers[0].next;
for (i=1; i<linkList->length; ++i)
{
// 第i个记录在linkList中的当前位置应不小于i
// 找到第i个记录,并用p指示其在linkList中当前位置
while (p<i)
{
p = linkList->numbers[p].next;
}
q = linkList->numbers[p].next; // q指示尚未调整的表尾
if (p!= i)
{
temp=linkList->numbers[p];
linkList->numbers[p]=linkList->numbers[i];
linkList->numbers[i]=temp;
// 指向被移走的记录,使得以后可由while循环找回
linkList->numbers[i].next=p;
}
// p指示尚未调整的表尾,为找第i+1个记录作准备
p=q;
}
}
最后调整后结构如下图:
最后:
一、该算法flash演示地址:
http://comic.sjtu.edu.cn/thucs/GD_jsj_002b/flash/chap10/10-2-4.swf
二:程序源文件及swf格式演示文件共享地址:
http://115.com/folder/fauqylsp#表插入排序
三、115网盘好像发布不了swf格式文件了,所以用数据银行又发布了一下,地址如下: