链 表

本文介绍了在C++中如何操作链表,包括删除链表节点、删除倒数第N个节点、反转链表、合并有序链表、判断链表是否为回文以及检测链表环。涉及的方法有头插法、尾插法、递归和数据结构如哈希表的使用。
摘要由CSDN通过智能技术生成

3_1 删除链表中的节点

Answer-将被删节点下一个val复制到待删除节点,然后将待删节点直接连接到下下一个节点即可。

学到:

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode(int x) : val(x), next(NULL) {}

 * };

 */

c++中结构体可以看作一个权限为public的类。其拥有成员变量、成员函数、构造函数等。

ListNode(int x) : val(x), next(NULL) {}就是构造函数的列表初始化操作。

3_2 删除链表的倒数第N个节点,给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

My-获取长度再跑到待删除节点前节点进行删除即可

Answer-快慢指针、栈

学到:初始化一个链表

结构体:

struct ListNode{
    int val;
    ListNode* next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode* next) : val(x), next(next) {}
};

初始链表并链上:

ListNode* head[5];
for (int i = 0; i < 6; i++)
{
    head[i] = new ListNode(i + 1);
}
for (int i = 0; i < 6; i++)
{
    head[i]->next = head[i + 1];
}
head[5]->next = nullptr;

注意:结构体声明再.h中只需要include  .h即可不用包含.cpp文件,不然会导致多重定义的符号的错误。

3_3 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

My-头插法

Answer-递归方法,1->2->3->4->5   

  1. 1->2->3->4<-5
  2. 1->2->3<-4<-5
  3. 1->2<-3<-4<-5
  4. 1<-2<-3<-4<-5

核心 head->next->next = head ;

注意:

ListNode* reverseList(ListNode* head) {

        ListNode* p = head;

        ListNode* result = new ListNode();

        result->next = nullptr;

        while(p != nullptr)

        {

            ListNode *q = p;

            p = p->next;

            q->next = result->next;

            result->next = q;

            

        }

        return result->next;

    }

 头插法时,一定让 p = p->next;紧跟ListNode *q = p;后,不然就找不到原本的顺序了。

3_4 合并两个有序链表

 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

My-双指针分别遍历若当前所遍历list1节点小于当前遍历list2节点,则当前list1插入合并链表,并且list1当前节点指针后移,反之list2指针加入合并链表并后移。若相等则都加入合并链表并后移。

Answer-递归,子问题划分,即list1与list2中较小的指向调用递归函数返回的结果,递归参数为(较小的节点的next和另一个链表中的节点)。

退出条件:

        if (list1 == NULL) {
            return list2;
        }
        if (list2 == NULL) {
            return list1;
        }

学习到:写法更加简易

r尾插p直接

r->next = p;

r = r->next;

即可

3_5 回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

My-借助栈先遍历入栈,再重新遍历并 逐个出栈比较,出现不相等即是非回文链表。

Answer-方法一:复制val到数组再进行前后向中间走进行双指针判断。

             方法二:递归,可以利用递归进行链表的方向遍历

void  print_node_val(ListNode *head)

{

     if(head != nullptr)

     { 

           print_node_val(head->next);

           cout << head->val << endl;

     }

}

currentNode 指针是先到尾节点,由于递归的特性再从后往前进行比较。frontPointer 是递归函数外的指针。若 currentNode.val != frontPointer.val 则返回 false。反之,frontPointer 向前移动并返回 true。

bool recursivelyCheck(ListNode* currentNode) {
        if (currentNode != nullptr) {
            if (!recursivelyCheck(currentNode->next)) {
                return false;
            }
            if (currentNode->val != frontPointer->val) {
                return false;
            }
            frontPointer = frontPointer->next;
        }
        return true;
    }
来源:力扣(LeetCode)

学到了:

C++栈的使用

//导入

include ”stack“

//初始栈

stack<int> mystack;

//入栈

mystack.push(val);

//出栈,返回为void

mystack.pop();

//获取栈顶元素

int a = mystack.top();

//栈空判断,空返回1非空为0

mystack.empty();

3_6判断链表是否有环

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

Answer-

方法一:快慢指针 两个指针一个走的快一个慢,若存在环则快指针一定会追上慢指针。

方法二:哈希表,注意哈希表存储节点。

核心:unordered_set<ListNode*> myset;

回顾:unorderd_set操作

定义unordered_set<datatype> set_name;

添加 myset.emplace(value);

查找myset.find(value); //返回为一个迭代器,auto类型 若未找到则返回myset.end() 否则返回一个正向迭代器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DQ小恐龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值