表插入排序

     以下内容主要参考了严蔚敏版的数据结构教材。
     表插入排序和直接插入排序的原理一样,也是将待插入的元素插入到一个已经排好序的子序列中。不过这里待排序的记录不是放在一个数组结构中而是放在一个静态链表中。插入过程中没有记录的移动,而只有静态链表节点的指针值的变化。但是关键字的比较的数量级和直接插入排序是一样的,因此表插入排序的时间复杂度还是 O ( n 2 ) O(n^2) O(n2)
     为了插入操作的方便这里引入了一个额外的记录,它的关键字是所有可能的待插入的记录的关键字中最大的并且这里的静态链表是循环链表。因此该关键字最大的记录的 n e x t next next值永远指向链表的第一个记录。一个排序的简单例子如图1所示。

 
图1.

     排好序之后只能从 M Y _ M A X I M U M MY\_MAXIMUM MY_MAXIMUM指向的第一个元素顺序访问每一个记录。为了能够随机存取,我们可以根据链表索引将每一个元素放到其对应的数组位置上,比如在图1中 M Y _ M A X I M U M MY\_MAXIMUM MY_MAXIMUM指向的第一个元素位于数组索引为6的位置上,但是现在我们要将它放到数组索引为1的位置上,数组索引为0的位置上依然放关键字为 M Y _ M A X I M U M MY\_MAXIMUM MY_MAXIMUM的那个元素。在实现过程中是顺着指针一个元素一个元素的去重新归位的,这里一共有p和q两个指针,p指向链表中当前需要归位的元素,q指向链表中当前需要归位的元素的下一个元素。当p指向的元素和位置i的元素互换之后,此时i指向的记录的 n e x t next next值应设为p。对于当前的i,表明 1 − > ( i − 1 ) 1->(i-1) 1>(i1)个较小的元素已经归位完毕,如果此时发现当前的 p < i p<i p<i,则应顺着p的 n e x t next next值找到 p > = i p>=i p>=i的p值,因为前 1 − > ( i − 1 ) 1->(i-1) 1>(i1)的元素已经归位好了,不应该再去移动它们,前面在互换元素后更改i指向的记录的 n e x t next next值应为p也是应这点要求。对于图1的结果的归位见图2。

 
图2.
#define MY_MAXIMUM 1000000
#define TABLE_SIZE 10

/* Function to print an array */
void printArray(int arr[], int size)
{
	int i;
	for (i = 0; i < size; i++)
		cout << arr[i] << " ";
	cout << endl;
}

typedef struct
{
	int data;
	int next;
}SLNode;

void tableSort(int arr[],int n)
{
	SLNode table[TABLE_SIZE];
	table[0].data = MY_MAXIMUM;
	table[0].next = 1;
	table[1].next = 0;
	int p = 0;
	int q = 0;


	for (int k = 0; k < n; k++)
	{
		table[k+1].data = arr[k];
	}
	//对初始列表进行排序()只是改变其对应的next域的指针值
	for (int i = 1; i < n; i++)
	{
		int currentIndex = table[0].next;
		int preIndex = table[0].next;
		int j = 0;
		for (;j<i;j++)
		{
			if (table[currentIndex].data < arr[i])
			{
				preIndex = currentIndex;
				currentIndex = table[currentIndex].next;
			}
			else
				break;
		}
		if (j == i)//如果待插入的元素大于有序序列的最大的元素
		{
			table[i+1].next = 0;
			table[preIndex].next = i+1;
		}
		else if (j==0)//如果待插入的元素小于有序序列的最小的元素
		{
			table[i + 1].next = currentIndex;
			table[0].next = i+1;
		}
		else//如果待插入的元素位于有序序列最小元素和最大元素之间
		{
			table[i + 1].next = currentIndex;
			table[preIndex].next = i + 1;
		}
	}
	//根据已经排好序的序列的元素的next域的指针值将元素放到正确的位置
	p = table[0].next;
	q = 0;
	for (int i=1;i<n;i++)
	{
		while (p < i)
		{
			p= table[p].next;
		}
		q= table[p].next;
		if (p!=i)
		{
			int tempData= table[p].data;
			int tempNext = table[p].next;
			table[p].data= table[i].data;
			table[p].next = table[i].next;
			table[i].data = tempData;
			table[i].next = p;
		}
		p = q;
	}
	for (int i=0;i<n;i++)
	{
		arr[i] = table[i + 1].data;
	}
	return;
}
//测试程序
int main()
{
	int arr[] = { 49, 38, 65, 97, 76, 13,27 };
	int n = sizeof(arr) / sizeof(arr[0]);
	tableSort(arr,  n );
	cout << "Sorted array: \n";
	printArray(arr, n);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qqssss121dfd

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

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

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

打赏作者

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

抵扣说明:

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

余额充值