【数据结构】单链表的应用

1 相交链表

判断链表是否相交:两个链表的尾节点相同,两个链表一定相交

思路:(1)求两个链表的长度,求得两个链表的长度差为x

             (2)让表较长的表头先走x步

              (3)让两个指针一起走,看走到链表尾部前是否有两个链表指向相同的情况(找相同的节点)

链表相交有三种情况:

代码如下:

typedef struct LIstNode ListNode
struct LIstNode* getTntersectionNode(struct ListNode)
{
  //求链表长度
  ListNode* pa = headA;
  ListNode* pb = headB;
  int sizaA = 0,sizeB = 0;
  while(pa)
   {
     ++sizeA;
     pa = pa->next;
   }
  while(pb)
   {
     ++sizeB;
     pb = pb->next;
   }
//求长度差
 int gap = abs(sizeA - sizeB);
//定义长短链表
 ListNode* shortList = headA;
 ListNode* longList = headB;
 if(sizeA >sizeB)
  {
     ListNode* shortList = headB;
     ListNode* longList = headA;
   }
//让长链表先走gap
 while(gap--)
  {
    longList = longList->next;
   }
//两个链表在同一起跑线
  while(shortList) //也可以写while(longList)
  {
    if(shortList == longList)
      {
        return shortList;
      }
    shortList = shortList->next;
    longList = longLiat->next;
  }
//链表不相交
 return  NULL:
}

2 环形链表(1)

思路:快慢指针,慢指针每次走一步,快指针每次走两步。如果slow和fast指向同一节点,说明该链表带环。

typedef struct ListNode ListNode
bool hasCycle (struct ListNode* head)
{
//创见快慢指针
 ListNode* slow = head;
 ListNode* fast = head;
 while(fast && fast->next)
  {
    if(slow == fast)
      return true:
    slow = slow->next;
    fast = fast->next->next;
  }
//链表不带环
 return false;
}

在环形链表中,慢指针每次走一步,快指针每次走2,3,4,5........步,快慢指针在环形链表中一定会相遇

3 环形链表(2)

思路:快慢指针,在环里一定会相遇。

相遇点到入环节点的距离 == 头节点到入环节点的距离

typedef struct ListNode ListNode
struct ListNode* detectCycle (struct ListNode *head)
{
 //创建快慢指针
 ListNode* slow = head;
 ListNode* fast = head;
 while(fast&&fast->next)
 {
   slow = slow->next;
   fast = fast->next->next;
   if(slow == fast)
    {
      //相遇点————找入环点(相遇点到入入环点的距离 == 头节点到入环节点的距离)
      ListNode* pcur head;
      while(pcur != slow)
      {
        pcur = pcur->next;
        slow = slow->next;
      }
      return pcur;//走到了入环节点
    }
 }
//链表不带环
 return NULL;
}

4 链表分割

思路:创建两个链表(小链表,大链表),遍历原链表,小的尾插到小链表中,大的尾插到大链表中,大链表和小链表首尾相连

ListNode* partition(ListNode* pHead,int x)
{
 ListNode* lessHead,*lessTail;
 lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));
 ListNode* greaterHead,*greaterTail;
 greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));
 
ListNode*pcur = pHead;
//遍历原链表
while(pcur)
 {
   if(pcur->val < x)
   {
     lessTail->next = pcur;
     lessTail = lessTail->next;
   }   
   else
   {
    greaterTail->next = pcur;
    greaterTail =greaterTai->next;
   }
  }
//将大链表的尾节点的next指针置为空,防止死循环
 greaterTail->next = NULL;
 lessTail->next = greaterHead->next;
 ListNode* del = lessHead->next;
 free(lessHead);
 free(greaterHead);
 return del;
}

5 随机链表的复制

#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构体
typedef struct Node {
    int val;
    struct Node* next;
    struct Node* random;
} Node;

// 创建新节点
Node* buyNode(int x) {
    Node* newnode = (Node*)malloc(sizeof(Node));
    newnode->val = x;
    newnode->next = newnode->random = NULL;
    return newnode;
}

// 在原链表每个节点后插入拷贝节点
void AddNode(Node* head) {
    Node* pcur = head;
    while (pcur) {
        Node* newnode = buyNode(pcur->val);
        Node* next = pcur->next;
        newnode->next = next;
        pcur->next = newnode;
        pcur = next;
    }
}

// 设置拷贝节点的 random 指针
void setRandom(Node* head) {
    Node* pcur = head;
    while (pcur) {
        Node* copy = pcur->next;
        if (pcur->random) {
            copy->random = pcur->random->next;
        }
        pcur = copy->next;
    }
}

// 复制带 random 指针的链表
struct Node* copyRandomList(struct Node* head) {
    if (head == NULL) {
        return head;
    }
    // 在原链表基础上拷贝结点并插入在原链表中
    AddNode(head);
    // 设置 random
    setRandom(head);
    // 断开新链表
    Node* pcur = head;
    Node* copyHead, * copyTail;
    copyHead = copyTail = pcur->next;
    while (copyTail->next) {
        pcur = copyTail->next;
        copyTail->next = pcur->next;
        copyTail = copyTail->next;
    }
    return copyHead;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值