1. 程式人生 > >不相交集ADT--鏈表實現

不相交集ADT--鏈表實現

+= 交換 return 合成 簡單實現 lis turn 思想 對象

每一個集合用用一個鏈表來表示。鏈表的第一個對象作為它所在集合的代表。鏈表中每個對象都包含一個集合成員,一個指向下一個對象的指針,以及指向代表的指針。每個鏈表含head和tail指針,head指向鏈表的代表,tail指向鏈表中最後的對象。

如下圖所示:

技術分享

Union的簡單實現:將x所在的鏈表拼接到y所在鏈表的表尾。對於原先x所在鏈表中的每一個對象都要更新其指向代表的指針。

如下圖所示:

技術分享

根據以上思想,代碼如下:

#include<iostream>

using namespace std;

#define NumSets 8

typedef struct Node *Position;
typedef struct Node *Head;
typedef Head DisjSet[NumSets + 1];

//對於頭節點,head_node指向第一個元素,tail指向最後一個元素,Key為該集合的大小
//對於普通節點,head_node指向第一個元素,tail指向後面的一個元素,相當於Next,Key為關鍵字
struct Node
{
   Position head_node;
   Position tail;
   int Key;
};

Head Make_One_Node (int x)
{
   Head Head_one = (Head)malloc(sizeof(Node));   //先申請一個頭結點
   Head_one->Key = 1;  //個數為1

   Position p = (Position)malloc(sizeof(Node));   //這個節點才是存儲數據的節點

   p->Key = x;
   p->head_node = p;    //普通節點的hand_node域指向第一個元素,此時就是它本身
   p->tail = NULL;

   Head_one->head_node = p;   //頭節點的hand_node域指向第一個元素
   Head_one->tail = p;    //頭節點的tail域指向最後一個元素

  
   return Head_one;
}
void Set_Union (Head head1, Head head2)
{
	Head tempHead;
    if (head1->Key < head2->Key )
    {
        tempHead = head1;
        head1 = head2;
        head2 = tempHead;
    }

	//把短的接在長的後面
	
	//下面兩句話的位置不能交換,否則會陷入死循環
    head1->tail->tail = head2->head_node;  //head1最後一個元素的tail域指向head2的第一個元素
	head1->tail = head2->tail ;  //head1的tail域指向head2的最後一個元素,也就是head2->tail

	Position p = head2->head_node ;
	while(p)
	{
	   p->head_node = head1->head_node ;//head2的所有元素都指向head1的第一個元素
	   p = p->tail;
	}
	head1->Key  += head2->Key ;

	//釋放head2的所有元素
	head2->Key = 0;
	head2->head_node = NULL;
	head2->tail = NULL;

}

Head Set_Find (DisjSet S,int x)   //返回該節點的頭結點
{
	for (int i = 1; i <= NumSets; ++i)
	{
	   Position p = S[i]->head_node ;
	   while(p)
	   {
	       if(x == p->Key )
			   return p->head_node;
		   else
			   p = p->tail;
	   }
	   
	}
}

void printf_list(DisjSet S)
{
	for (int i = 1; i <= NumSets; ++i)
	{
		if(S[i]->Key == 0)
		{
		   cout << "第 "<< i << " 個集合沒有元素。" <<endl;
		}
		else
		{
		   cout << "第 "<< i << " 個集合一個共有 " << S[i]->Key  << " 個元素,分別是:";
			Position p = S[i]->head_node ;
			while(p)
			{
			   cout << p->Key << "\t";
			   p = p->tail;
			}
			cout << endl;
		}
	     
	}
   
}

int main ()
{
	DisjSet S;
	for (int i = 1; i <= NumSets; ++i)
	{
	    S[i] = Make_One_Node (i);
	}
	Set_Union (S[1], S[2]);
	Set_Union (S[3], S[4]);
	Set_Union (S[3], S[1]);
	printf_list(S);

	cout << Set_Find (S,5)->Key << endl;

  return 0;
}

  看著比數組實現要復雜一點啊。

夜深了,,,

今天5月20號啊,520啊,還是周末啊,還在寫代碼,代碼才是真愛。

不相交集ADT--鏈表實現