• 不相交集ADT--链表实现


         

           每一个集合用用一个链表来表示。链表的第一个对象作为它所在集合的代表。链表中每个对象都包含一个集合成员,一个指向下一个对象的指针,以及指向代表的指针。每个链表含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 << "	";
    			   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啊,还是周末啊,还在写代码,代码才是真爱。

  • 相关阅读:
    【剑指offer】数字在排序数组中出现的次数
    移动互联网的架构设计浅谈一
    Android开发中遇到的adb问题解决方法
    Datagrid分页、排序、删除代码
    新辰:关于个人站点安全问题的分析及对策探讨
    Android开发中,activity页面跳转后是空白
    实战——二、c#窗体(2)
    实战——一、c#窗体(1)
    c#的sealed修饰符
    c#中,类的重写中,new和override的区别
  • 原文地址:https://www.cnblogs.com/1242118789lr/p/6882783.html
Copyright © 2020-2023  润新知