0
点赞
收藏
分享

微信扫一扫

日志和数据库备份

悬灸人雪洋 2024-07-26 阅读 27

【C算法】——链表

移除链表元素

链接: 移除链表元素

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) 
{
   //设置俩个指针
   //prev用来记录val前面的指针
   //假设将prev的指向head的前面,即为NULL
   struct ListNode* prev = NULL;
   //cur用来判断,cur指向链表第一个
   struct ListNode* cur = head;
   //利用prev和cur进行循环
   //当cur为NULL停止
   while(cur != NULL)
    {
      
        if(cur->val != val)
        {
            //cur的值不等于val时
            //prev向后移动一步
            //cur向后移动一步
            prev = cur;
            cur = cur->next;
        }
        else
        {
            //判断如果一个值为val时,此时prev任然为NULL;
            //需要将这种cur向后移
            if(prev == NULL)
            {
                //将head指向下一个
                head = cur->next;
                //释放cur
                free(cur);
                //cur重新指向head的值
                cur = head;
            }
            else
            {
                //cur的值等于val时
                //将prev指向的地址向后移动一步
                prev->next = cur->next;
                //释放cur所在的内存
                free(cur);
                //将粗人指向新的prev后面的位置
                cur = prev->next;
            }
              
        }
        
    }
    return head;
}

链表的中间结点

链接: 链表的中间结点

在这里插入图片描述

代码详解:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) 
{
    //定义一个快指针,一次走俩格
    struct ListNode* fast = head;
    //定义一个慢指针,一次走一格
    struct ListNode* slow = head;
    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

返回倒数第k个结点

链接: 返回倒数第k个结点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


int kthToLast(struct ListNode* head, int k)
{
    //定义一个先走指针,
    struct ListNode* fast = head;
    //定义一个慢走指针
    struct ListNode* slow = head;
    //先走指针比慢走指针快k步
    while(k--)
    {
        fast = fast->next;
    }
    //俩个指针一起走
    while(fast != NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow->val;
}

合并俩个有序链表

链接:合并俩个有序链表
在这里插入图片描述

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
	//设置四个结点
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    struct ListNode* head = NULL;
    struct ListNode* end = NULL;
    //判断如何都不为空
    if (cur1 && cur2)
    {
    //将合并后头结点head指向小值
        if (cur1->val < cur2->val)
        {
            head = end = cur1;
            cur1 = cur1->next;
        }
        else
        {
            head = end = cur2;
            cur2 = cur2->next;
        }
    }
    //cur1与cur2都不为空所以不需要判断else,如果没有else,设置完头结点head后,有一个可能为空,导致返回。
    else if (cur1 == NULL)//cur1为空,返回cur2
    {
        return cur2;
    }
    else if (cur2 == NULL)//cur2为空。返回cur1
    {
        return cur1;
    }
    //俩个都不为空进行插入链表
    while (cur1 && cur2)
    {
    //每次插入都需要,将cur和end向后移动
        if (cur1->val <= cur2->val)
        {
            end->next = cur1;
            cur1 = cur1->next;
            end = end->next;
        }
        else
        {
            end->next = cur2;
            cur2 = cur2->next;
            end = end->next;
        }
    }
    //如果其中一个为空,可以直接将另一个后面的全部接在end后面
    if (cur1 == NULL)
    {
        end->next = cur2;
    }
    if (cur2 == NULL)
    {
        end->next = cur1;
    }
    return head;
}

链表分割

链接:链表分割

在这里插入图片描述

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) 
    {
        //创建俩个哨兵结点
        //使用begin1与end1指向第一个哨兵
        //使用begin2与end2指向第二个哨兵
        struct ListNode* begin1;
        struct ListNode* begin2;
        struct ListNode* end1;
        struct ListNode* end2;
        begin1 = (struct ListNode*)malloc(sizeof(struct ListNode));
        begin2 = (struct ListNode*)malloc(sizeof(struct ListNode));
        if(begin1 == NULL || begin2 == NULL)
        {
            perror("malloc fail");
            return NULL;
        }
        begin1->next = NULL;
        begin2->next = NULL;
        end1 = begin1;
        end2 = begin2;
        //将小于x的结点接在begin1后面
        //将大于等于x的结点接在begin2后面
        while(pHead != NULL)
        {
            if(pHead->val < x)
            {
                end1->next = pHead;
                end1 = end1->next;
            }
            else
            {
                end2->next = pHead;
                end2 = end2->next;
            }
            pHead = pHead->next;
        }
        //将end1与end2后面置空
        end1->next = NULL;
        end2->next = NULL;
        //将大于等于x的结点接在小于x的结点后面
        end1->next = begin2->next;
        //将小于x的第一个结点设置为头结点
        pHead = begin1->next;
        //注意需要释放malloc创建的堆区已经野指针问题
        free(begin1);
        free(begin2);
        begin1 = begin2 = end1 = end2 = NULL;

        return pHead;
    }
};

相交链表

链接: 相交链表
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    //设置L1和L2计算俩条链的长度
    int L1 = 1, L2 = 1;
    //设置俩个指针指向俩条链的头结点
    struct ListNode* cur1 = headA;
    struct ListNode* cur2 = headB;
    //计算L1的长度
    while(cur1->next != NULL)
    {
        cur1 = cur1->next;
        ++L1;
    }
    //计算L2的长度
    while(cur2->next != NULL)
    {
        cur2 = cur2->next;
        ++L2;
    }
    //判断如果俩个直接的最好交点不在一起则直接返回NULL
    if(cur1 != cur2)
    {
        return NULL;
    }
    //计算链的长度差
    int L = L1 - L2;
    //将移动的指针重新指向头结点
    cur1 = headA;
    cur2 = headB;
    //让长度较长的指针先走L步
    if(L > 0)
    {
        while(L--)
        {
            cur1 = cur1->next;
        }
    }
    else
    {
        while(L++)
        {
            cur2 = cur2->next;
        }
    }
    //俩个指针同时走,发现相同时停止
    while(cur1 != cur2)
    {
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}

环形链表

链接: 环形链表
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) 
{
    //判断是否存在空链表或者链表中只存在一个结点
    if(head == NULL || head->next == NULL)
    {
        return false;
    }
    //定义一个快结点和慢结点
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    //快结点一次走俩步
    //慢结点一次走一步
    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
        //相遇时结束
        if(fast == slow)
        {
            return true;
        }
    }
    return false;
}

链表的回文结构

链接: 链表的回文结构

在这里插入图片描述

难点:使用三个指针翻转链表时,循环停止的条件为中间的指针为空,此时需要第三个结点在循环内初始化,这样才能保证后面每一个链表都能翻转过来,并且当第三个结点为空时,不会执行next

  • 代码实现:
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) 
    {
        //链表为空或者链表只有一个返回true
        if(A == NULL || A->next == NULL)
        {
            return true;
        }
        //设置快慢指针
        //快指针一次走俩步
        //慢指针一次走一步
        struct ListNode* fast = A;
        struct ListNode* slow = A;
        //寻找中间结点
        while(fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        //slow此时所在位置为中间结点
        //从中间结点往后开始翻转链表
        struct ListNode* cur = slow->next;
        while(cur != NULL)
        {
            struct ListNode* cur_next = cur->next;
            cur->next = slow;
            slow = cur;
            cur = cur_next;
        }
        //设置一个头结点和尾结点
        struct ListNode* tail = slow;
        struct ListNode* head = A;
        //一前一后开始比较
        //比较正确,比较下一个
        //比较错误,返回错误
        while( head != tail)//奇数时二者相遇
        {
            if(head->val != tail->val)
            {
                return false;
            }
            if(head->next == tail)
            {
                //偶数时head的下一个是tail
                return true;
            }
            head = head->next;
            tail = tail->next;
        }
        return true;
    }
};
举报

相关推荐

0 条评论