数据结构:求集合差集(c/c++)

用带头结点的单链表表示整数集合,完成以下算法并分析时间复杂度:

(1)设计一个算法求两个集合A和B的差集运算,即C=A-B,要求算法的空间复杂度为O(1),并释放单链表A和B中不需要的结点。

(2)假设集合中的元素按递增排列,设计一个高效算法求两个集合A和B的差集运算,即C=A-B,要求算法的空间复杂度为O(1),并释放单链表A和B中不需要的结点。

#include
#include

typedef struct LNode
{
	int data;
	struct LNode* next;
} LinkNode;

void DestroyList(LinkNode*L)  //销毁线性表函数
{
	LinkNode*p=L->next,*q=L;
	while(p!=NULL)
	{
		free(q);
		q=p;
		p=p->next;
	}
	free(q);
}

void DispList(LinkNode*L)    //输出函数
{
	LinkNode*p=L->next;
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
}

void CreatList(LinkNode*&L,int a[],int n)     //数组数据建立链表函数尾插法
{
	LinkNode*p,*q;
	L=(LinkNode* )malloc(sizeof(LinkNode));
	q=L;
	for(int i=0;idata=a[i];
		q->next=p;
		q=p;
	}
	q->next=NULL;
}


void diff1(LinkNode*&A,LinkNode*&B)      //第一小题函数
{
	LinkNode*a,*b,*a_prior,*b_prior;     //a_prior,b_prior分别为遍历循环中a,b节点的前驱节点
	a_prior=A;
	int T;                               //辅助变量T
	for(a=A->next;a!=NULL;a=a->next)     //遍历A中元素
	{
		b_prior=B;
		T=1;
		for(b=B->next;b!=NULL;b=b->next) //对A中,每一个元素都遍历一遍B表
		{
			if(a->data==b->data)         //若两表中出现相同元素,则删除A,B中此元素所在节点(删除B中节点为减少以后遍历B表次数)
			{
				T=0;
				a_prior->next=a->next;   //跳过a元素将a前后元素链接
				free(a);
				a=a_prior;               //∵这里if后break跳过B循环后A循环会执行a节点前移,既下一刻开始判断被删除节点的下一节点
				b_prior->next=b->next;   //跳过b元素将b前后元素链接
				free(b);
				b=b_prior->next;
				break;
			}
			b_prior=b_prior->next;         
		}
		if(T) //若T==0说明原a节点已删除,此刻a节点位置为a_prior位置,下一刻a节点前移,∴a_prior作为a节点的前驱节点此时就不必前移了
    		a_prior=a_prior->next;
	} 
}


void diff2(LinkNode*&A,LinkNode*&B)   //第二小题函数
{
	LinkNode*a=A->next,*b=B->next,*a_prior=A;  //a_prior为a节点的前驱节点
	while(a!=NULL && b!=NULL) 
	{
		if(a->data > b->data)         //若a节点的值大于b节点,则b节点后移
			b=b->next;
		else if(a->data < b->data)    //若a节点的值小于b节点,则a节点后移
		{
			a_prior=a;                //先将a的前驱节点前移,再将a节点前移
			a=a->next;
		}
		else                          //若两值相等,则删a节点
		{                             //b不必删除 ∵到后面有销毁函数销毁b,这里删除b并不能像第一题一样减少遍历次数
			a_prior->next=a->next;    //跳过a元素将a前后元素链接
			free(a);
			a=a_prior->next;
		}
	}
}

void main()
{
	int A[7]={9,5,6,7,1,8,2},B[4]={8,-1,5,3};          //无序数组,集合运算A-B应该为9,6,7,1,2 (以检测结果)
	int a[10]={0,1,2,3,4,5,6,7,8,9},b[5]={2,4,6,8,10}; //有序数组,集合运算a-b应该为0,1,3,5,7,9
	LinkNode*LA=NULL,*LB=NULL;
	CreatList(LA,A,7);          //建立无序链表LA,LB
	CreatList(LB,B,4);
	diff1(LA,LB);               //第一题函数
	DestroyList(LB);            //根据题目要求释放A和B中不需要的节点,则B链表全删
	DispList(LA);               //最后(1)题答案即为diff1后的链表A,将答案输出
	DestroyList(LA);            //第一题已完成,删除原表LA,重置A,B表并开始(2)题
	CreatList(LA,a,10);         //建立有序表A,B
	CreatList(LB,b,5); 
	diff2(LA,LB); 
	DestroyList(LB);
	DispList(LA);
	DestroyList(LA);
}


数据结构:求集合差集(c/c++)_第1张图片


你可能感兴趣的:(数据结构:求集合差集(c/c++))