1. 程式人生 > >單向連結串列的應用舉例

單向連結串列的應用舉例

1.單向連結串列的倒置

思路:取原連結串列的每一個結點,將其作為第一個結點插入到新連結串列中。

template<class Type>
void LinkedList <Type> :: Inverse ()
{
	ListNode<Type> *p, *head = new ListNode<Type> ();
	while (first != NULL) 
    {
		p = first;  
        first = first->link;		//摘下first鏈頭結點  
		p->link = head->link;  
		head->link = p;	//插入head鏈前端
	}
	first = head->link; 
	delete head;			//重置first
}


2.實現一個Locate運算的函式,使頻繁訪問的結點總是靠近表頭。

思路:利用雙向連結串列的特點,若找到,修改訪問頻度域,順左鏈查詢適當的位置插入。

#include <iostream>

//雙向迴圈連結串列結點的建構函式
DoubleNode(Type value, DoubleNode<Type> * lLink, DoubleNode<Type> *rLink) :
	data(value), freq(0), left(lLink), right(rLink) {}
DoubleNode(Type value) :
	data(value), freq(0), left(NULL), right(NULL) {}

template <class Type>
DoubleList<Type> :: DoubleList (Type uniqueVal)
{
	first = new DoubleNode<Type>(uniqueVal);
	first->right= first->left = first;		//建立表頭結點
	current = NULL;
	cout << "開始建立雙向迴圈連結串列:\n";
	Type value;
	cin >> value;
	while (value != uniqueVal)
    {		//每次新結點插入在表頭結點後面
   		first->right = new DoubleNode<Type>(value, first, first->right);
   		cin >> value;
	}
}

template <class Type>
void DoubleList<Type> :: Locate (Type & x)
{
	DoubleNode<Type> *p = first->right;
	while (p != first && p->data != x) p = p->right;
	if (p != first)      //連結串列中存在x
    {
	  	p->freq++;						//該結點的訪問頻度加1
		current = p;						//從連結串列中摘下這個結點
		current->left->right = current->right;
		current->right->left = current->left;
		p = current->left;					//尋找從新插入的位置
		while (p != first && current->freq > p->freq)
			p = p->left;
		current->right = p->right;			//插入在p之後
		current->left = p;
		p->right->left = current;
		p->right = current;
	}
	else cout << "Sorry. Not find!\n";		//沒找到
}
//假設表中元素個數為n,則該演算法的時間複雜度為O(n)

3.union-find問題(並查集)

線上等價類問題

void Initialize(int n)  //初始化n個類, 每個類僅有一個元素
{
    node = new EquivNode[n + 1];
    for (int e = 1; e <= n; e++)
    {
        node[e].E = e;
        node[e].link = 0;
        node[e].size = 1;
    }
}

void Union(int i, int j)  //合併類i和類j, 使i代表較小的類
{
    if (node[i].size > node[j].size)
        swap (i, j);
    //改變較小類的E值
    int k;
    for (k = i; node[k].link; k = node[k].link)
        node[k].E = j;
    node[k].E = j; //鏈尾結點
    //在連結串列j的首結點之後插入連結串列i, 並修改新連結串列的大小
    node[j].size += node[i].size;
    node[k].link = node[j].link;
    node[j].link = i;
}

int Find(int e)
{   //搜尋包含元素i的類
    return node[e].E;
}