鏈表排序(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"
	}
}




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