插入排序(二)— 表插入排序

上篇文章已经提到直接插入排序中,时间消耗在了元素间的比较次数和移动这两方面。折半插入排序可以减小比较次数,而表插入排序则可以避免元素移动。但它需要建立数据结构,并且需要额外的空间(省时一般都耗空间,这个在算法上很常见哦!)。

首先给出表结构,定义如下:

#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格式文件了,所以用数据银行又发布了一下,地址如下:

http://dl.dbank.com/c0mbh4bf9v

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naruto

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值