学习数据结构之链表

学习完了数据结构链表的部分,也看完了视频。

今天做下链表的课后题

题目:已知有两个带头节点的的单链表A和B,A和B中的元素中的元素按从小到大排列,设计一个算法,求A和B的交集C,将A和B中相同的元素插入到C中。

开始的错我在于我编写的MergeList函数的问题,错在对指针操作有误

void MergeList(LinkList A,LinkList B,LinkList *C)
{  
 int i=1;
 ListNode *pa,*pb,*pc;
 pa=A->next;
 pb=B->next;
 *C=A;(*C)->next=NULL;

 pc=*C;
 while(pa&&pb)
 {
  if(pa->data == pb->data)
  {

   pc->next=pa;
   pc=pa;
   pa=pa->next;
   pb=pb->next;
  }
  else
   if(pa->data < pb->data)
           pa=pa->next;
      else
        pb=pb->next;
 }
}

也发现出错误在于指针pa与pc转换时

void MergeList(LinkList A,LinkList B,LinkList *C)
{  
 int i=1;
 ListNode *pa,*pb,*pc;
 pa=A->next;
 pb=B->next;
 InitList(C);

 pc=*C;
 while(pa&&pb)
 {
  if(pa->data == pb->data)
  {
   InsertList(pc,i,pa->data);
   i++;
   pa=pa->next;
   pb=pb->next;
  }
  else
   if(pa->data < pb->data)
           pa=pa->next;
      else
        pb=pb->next;
 }
}

运行结果正确

关于求交集的算法,首先能想到的算法就是遍历法,对于排序好的是时间复杂度是O(N);

其次就是集合压缩,(该算法是参考)

对于一个集合来说,我们很容易就可以得到集合的最大值和最小值,假设集合A的最大值和最小值分别为MaxInA,MinInA;假设集合B的最大值和最小值分别为MaxInB,MinInB;那么集合A的所有元素一定在闭区间【MinInA, MaxInA】里面,集合B的所有元素一定在闭区间【MinInB, MaxInB】里面,从这两个集合里面我们可以作如下判断:(集合A和集合B都在链表中!此算法使用链表结构,操作起来比数组更方便)

  1. 若MinInA == MinInB或者MaxInA == MaxInB,那么MinInA 或者MaxInA (相等的那个数)就一定在交集里面,存入交集(可以用数组存),删除链表中相应的结点;若不想等则跳到第3步;

  2. 重新找到集合A和B中的最大值和最小值MinInA 、MaxInA 、MinInB、MaxInB;跳回第1步;

  3. 更新区间(交集的区间),区间的更新如下:区间下界为Lower = max(MinInA, MinInB),上届为Upper = min(MaxInA , MaxInB),那么剩下的交集一定在闭区间【Lower ,Upper】里面,按照这个区间来剔除掉集合A和集合B中不符合条件的元素,剔除结束后,若其中一个集合为空,跳到第4步,否则返回第2步;

  4. 程序结束,退出!

  这种适用于集合里面数值比较散乱,最大值最小值差值比较大的情况!算法的思想在于不断减小搜索的范围,时间的消耗主要在查找集合的最大值和最小值上,我们来看一个例子,集合A= {1, 3, 10, 100, 123, 0, 6} ,B = {3, 2, 10, 23, -1},

  集合A的闭区间【0, 123】,集合B的区间【-1,23】,交集的闭区间就为【0,23】,按照这个区间,剔除集合A中的{ 100, 123},剔除集合B的{-1},集合A={1, 3, 10, 0, 6}集合B={3, 2, 10, 23},没有相等的,继续缩小范围,为【2,10】,这时MaxInA == MaxInB,满足条件,把10存入交集数组中,剔除两个集合的结点;集合变为A= {3,6}集合B={3},满足MinInA == MinInB或者MaxInA == MaxInB,把3存入交集数组中,集合B为空,结束!如图:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值