图中黄色部分为(A-B)U(B-A)的实际意义,用结构数组做静态链表来实现该表达式
大致流程是先建立A链表,接着将挨个输入的B中元素在A链表中遍历。如果没找到,就加到A链表结尾下标为endpointer的位置之后。如果找到了,删除该节点(回收到备用链表中)。
需要注意的是:
- 每次拿着B中元素遍历A链表时,遍历到endpointer就停了。因为endpointer之后的都是B中元素,排除B中有相同元素的可能性,只用与A中元素(即endpointer之前的比较)
- 代码中,B中元素的插入方式,是在endpointer后以倒叙插入的方式插入,所以最先插入的,反倒在顺序上跑到了后面
/*该算法将每一个B中元素在A中遍历。若找到则删除,否则, 倒叙添加在endpointer位置之后。S为结果链。时间复杂度为O(m*n)*/ #define MAXSIZE 1000; typedef struct { ElementType data; int cur; }component,SLinkList[MAXSIZE]; /*初始化space结构数组作为备用链表,0指向1,1指向2...*/ void InitSpace(SLinkList &space) { for(int i = 0; i < MAXSIZE; i++) { space[i].cur = i + 1; } space[MAXSIZE - 1].cur = 0; } /*从备用链表分配一个节点出来*/ int MallocFromSpace(SLinkList &space) { int i = space[0].cur;//space[0]永远是备用链表的头节点 if(space[0].cur)//判断备用链表是否已为空 space[0].cur = space[i].cur; return i; } /*回收下标为k的空闲节点,始终把节点加在头节点之后*/ void FreeToSpace(SLinkList &space,int k) { space[k].cur = space[0].cur; space[0].cur = k; } /* (A-B)U(B-A) */ void difference(SLinkList &space, int &S) { int endPointer,tmp,Apre,Anow; InitSpace(space); S = MallocFromSpace(space);//这个是A集合的头节点,什么也没装 endPointer = S; scanf(m,n);//m是A集合的元素个数,n是B集合的元素个数 /*开始录入A集合*/ for(int i = 0; i < m; i++) { tmp = MallocFromSpace(space); space[endPointer].cur = tmp; scanf(space[tmp].data); endPointer = tmp; } space[endPointer].cur = 0; for(int j = 0; j < n; j++) { scanf(b); Apre = S; Anow = space[S].cur; while(space[Anow].data != b && Anow != space[endPointer].cur) {//比较到endpointer就停了,因为除非B中有重复的元素,不然没必要让B中的元素与B相比 Apre = Anow; Anow = space[Anow].cur; } if(space[Anow].data == b) {//有 space[Apre].cur = space[Anow].cur; FreeToSpace(space,Anow); if(Anow == endPointer) endPointer = Apre; //这个endpointer始终指着A的最后一个元素 } else {//没有 int tmp = MallocFromSpace(space); //用倒叙插入的方式将A中没有的B的元素插进去 space[i].cur = space[endPointer].cur; space[endPointer].cur = i; } } }