【排序】表插入排序算法(C语言版)

排序耗时的操作主要分为两种:查找比较、记录移位。


1.表插入排序

在查找比较基础上,尽量减少记录移位步数,可以令排序操作耗时降低,表插入排序正是为减少移位次数而出现的。

在数据结构上,数据是存储在静态数组(表)中,而每个数组除了数据关键字外还记录了表中下一个记录,按记录遍历的关键字则是排序的结果。

如:有如下需要排序的数据: 

关键字51324
下一个记录的表中位置-----

排序后得到的表为

关键字51324
下一个记录的表中位置-13420

这里还需要提到重排记录的方法:

由于重排过程中,需要移动记录的位置,所以"下一个记录的表中位置"则会产生变化,而又因为重排过程中表中不同数据只会被访问一次,所以可以利用失效的"下一个记录的表中位置"记录未被访问的数据且因重排被移位的新位置。

重排时,以i记录已经排好的记录数量,p记录要重拍的关键字,如果p<i,表示要重拍的关键字被移位了,所以再获取表中的"下一个记录的表中位置"即可。

#include <stdio.h>
#include <stdlib.h>

typedef struct{
	int data;
	int next;
}node;
typedef struct{
	node *list;
	int head;
}table;

int main(void){
	node *s;
	int cnt=0, k, cntmax=10, nexttemp, datatemp, kk;
	int head, preindex;
	int p,i;
	table mytable;

	s = (node*)malloc(sizeof(node)*10);
	while(1){
		scanf("%d", &datatemp);
		if(datatemp<0)
			break;
		(s+cnt)->data = datatemp;
		cnt++;
		if(cnt==cntmax){
			s = (node*)realloc(s, cntmax+10);
			cntmax += 10;
		}
	}
	mytable.list = s;

	head = 0;
	s->next = -1; //-1表示链表表尾结点
	//表插入排序
	for(k=1; k<cnt; k++){
		kk=head;
		while(kk!=-1){		
			if((s+kk)->data>(s+k)->data){
				if(kk==head){
					head = k;
					(s+k)->next = kk;
				}
				else{
					(s+preindex)->next = k;
					(s+k)->next = kk;
				}
				break;
			}
			else{
				preindex = kk;
				kk = (s+kk)->next;			
			}
		}
		if(kk==-1){
			(s+preindex)->next = k;
			(s+k)->next = -1;
		}
	}
	mytable.head = head;

	for(k=mytable.head; k!=-1; k=(mytable.list+k)->next){
		printf("%d ", (mytable.list+k)->data);
	}
	printf("\n");

	//记录重排-->这里是难点~~
	for(i=0, p=head; i<cnt; i++){
		//i位置结点与k位置结点交换
		while(p<i)  //----->注意这里哟,逐个找回来
			p = (s+p)->next;
		k = (s+p)->next;  //保存指向的下一个需要重排的关键字位置

		if(p!=i){
			datatemp = (s+p)->data;
			nexttemp = (s+p)->next;
			(s+p)->data = (s+i)->data;
			(s+p)->next = (s+i)->next;
			(s+i)->data = datatemp;
			(s+i)->next = p;
		}

		p = k;
	}
	for(i=0; i<cnt; i++){
		printf("%d ", (mytable.list+i)->data);
	}
	printf("\n");

	system("pause");
	return 0;
}

其他排序请见后篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值