链表排序(1)

前些天在论坛看到个帖子, 关于链表排序。

我首先想到的是, 将链表中的成员(member)进行交换, 这对於单成员来说方法是非常好的。 当链表的元素比较多, 而且结构复杂, 移动所有元素就不明智了。想象一下 Facebook 这么多的用户,用户属性又这么多,如果排序采取属性移动到特定空间的方法。这是多么吓人。

这时, 我们需要考虑采取移动链表指向的方法。 好比重新链接这个链条一样。 这个方法的好处之一可以解决上诉提到的类似 Facebook 成员链表中多属性(member)问题。

还有一个好处, 那就是按任意属性比较方式来排序(比如,身高比, 一种排序方式, 体重比一种排序方式), 而不需要移动其它元素, 节省大量空间时间。

上述两种方法好比搬家,换门牌号。 换门牌号当然轻松多了, 不过实际生活中, 人们不会这么干。 但是对于电脑处理链表来说, 就是顺藤摸瓜。 所以, 换门牌号简单。

现在讲讲第二个排序方法(第一个简单, 不再讲了)

采用的是冒泡排序, 但是由于链表不像数值那样自由访问, 必须先找到根(这里用 first 指向链表的第一个元素(根元素)), 不从根开始摸, 是不知道在哪里结尾的。 所以这次的冒泡排序(应称沉淀排序, 不过实质一样)是先找出最大的, 沉到最低。同时由于根访问特性, 使得一种更快的排序----------归并排序相当繁琐, 需要复制用来比较的成员和元素地址各一份, 故对于链表来说, 归并排序不见得优秀。

下面是其实现代码, 如果要完整的能运行的话。问我(1220645790,  或者看这里

void SortList(void);
void swap(node *left, node *middle, node *right);

void SortList(void)
{
	/********************************************************************************************
	* 1. "compare" use for compare
	* 2. "iterate" use for traversal, alway in front one position of "compare" before compare swap
	* 3. "last" use to mark the position which alreay sorted, maybe you can instead by "NULL", but
	* 		the number of comparisons will be times 2
	*********************************************************************************************/
	node *compare, *iterate, *last;

	last = NULL;	
	while (last != first->next)
	{
		// first elements as compare, mark(iterate) = NULL
		compare = first;
		iterate = NULL;
		if (compare->n > compare->next->n)
			swap(iterate, compare, compare->next);
		
		// not first element as compare, mark(that is iterate) = previous of compare
		for (iterate = first; iterate->next->next != last; iterate = iterate->next)
		{
			compare = iterate->next;
			if (compare->n > compare->next->n)
				swap(iterate, compare, compare->next);
				
		}
		
		last = iterate->next;
	}
	
}


void swap(node *left, node *middle, node *right)
{
	if (left == NULL)
	{
		first = right;
		middle->next = right->next;
		right->next = middle;
	}
	else
	{	left->next = right;
		middle->next = right->next;			// right->next must be last assignment, 
		right->next = middle;				// if not, may be lead to the last element's member "next" != "NULL"
	}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章