判断两链表是否相交,如果相交找到第一个交点

#include <stdio.h>
#include <stdlib.h>
typedef struct LinkNode
{
    struct LinkNode* next;
    int data;
}LinkList;
/*说明:都带头结点的单链表*/
/*创建链表*/
void createLinkList(LinkList* head, int* a, int n)
{
    int i = 0;
    LinkNode* node = NULL;
    while (i < n)
    {
        node = new LinkNode;
        node->next =  head->next;
        node->data = a[i];
        head->next = node;
        i++;
    }
}
/*获取链表的长度*/
int getLenOfList(LinkList* head)
{
   int i = 0;
   LinkNode* node = head;
   
   while (node->next != NULL)
   {
        i++;
        node = node->next;
   }
   
   return i;
}
/*获取链表的第K个节点*/
LinkNode* getKNode(LinkList* head, int K)
{
    LinkNode* p = head;
    
    while ((p->next!=NULL) && (K>0))
    {
        p = p->next;
        K--;
    }
    
    return (K>0) ? NULL:p;
}
/*注意此函数找不带环的链表,如果带环需要重新考虑*/
/*参考:http://blog.csdn.net/xiaodeyu2010xiao/article/details/42460203*/
/*备注:改博客应该遗漏还有一种情况,在成环的情况下,如果是如下情况的处理:
链表A:
O->O->O->O->O-->
   ^     ^      |
   |     |      |
   |      ------|
   |
   <----O<-O<-O<-O :链表B
   
方法其实很类似:判断是否成环,找到成环结点是否相同,如果相同的话,
则按照不想交的判断,取两链表长度,让长的先走N-M(N,M分别是两链表的长度)
然后同时向前走,如果结点相等且不是环结点退出,找到相交的第一个结点
*/
/*说明:改函数可以继续优化,如果根本就不想交直接判断最后一个结点是否相等退出*/
bool findFirstCommonNode(LinkList* l, LinkList*s,  LinkNode* &node)
{
    int n = getLenOfList(l);/*获取链表长度*/
    int m = getLenOfList(s);/*获取链表长度*/
    LinkNode* p;
    LinkNode* q;
    
    /*分别找到起点*/
    if (n > m)
    {
       p = getKNode(l, n-m);
       q = s;
    }
    else
    {
        p = getKNode(s, m-n);
        q = l;
    }
    
    /*往下走找到起点*/
    while (p!=NULL && q!=NULL)
    {
        if (p == q)
        {
            node = p;
            return true;
        }
        p = p->next;
        q = q->next;
    }
    return false;
}
/*将s链表尾节点添加到l链表的K个位置*/
bool appendKNode(LinkList* l, LinkList* s, int K)
{
      LinkNode* lastNode = s;
      LinkNode* node = l;
      
      while (lastNode->next != NULL)
      {
          lastNode = lastNode->next;
      }
      
      while (node->next!=NULL && (K>0))
      {
          node = node->next;
          K--;
      }
      
      if (K > 0)
      {
          return false;
      }
      
      lastNode->next = node;
      return true;
}
/*打印链表*/
void printLinkList(LinkList* head)
{
    LinkNode* node = head->next;
    while (node != NULL)
    {
        printf("%d\t", node->data);
        node = node->next;
    }
    printf("\n");
}
int main()
{
    /*创建链表*/
    LinkList l = {0};
    LinkNode* node = NULL;
    int a[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
    createLinkList(&l, a, 9);
    printLinkList(&l);
    
    /*创建链表*/
    LinkList s = {0};
    int b[] = {15, 14, 13, 12};
    createLinkList(&s, b, 4);
    printLinkList(&s);
    
    findFirstCommonNode(&l, &s, node);
    if (node != NULL)
    {
        printf("first common node %d\n", node->data);
    }
    else
    {
        printf("NO COMMON NODE\n");
    }
    /*将s链表尾节点添加到l链表的K个位置*/
    appendKNode(&l, &s, 3);
    printLinkList(&s);
    findFirstCommonNode(&l, &s, node);
    if (node != NULL)
    {
        printf("first common node %d\n", node->data);
    }
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值