首页 > 其他分享 >代码随想录打卡Day3

代码随想录打卡Day3

时间:2024-10-19 08:48:48浏览次数:18  
标签:index head ListNode cur 随想录 Day3 next 打卡 节点

链表:

通过指针链接的线性数据结构。链表由两部分组成,一为数据域,一为指针域。

并与结构体有很大关系,链表的节点一般都是结构体,其中包含了该节点的数据部分以及指向下一节点的指针。通过这种方式,链表将结构体与指针连接起来,从而构建一个强大的数据结构,可以同时实现数据的组织和动态管理。

定义结构体:

struct 结构体名称 {
    类型 成员1;
    类型 成员2;
    // 更多成员定义
};

单链表节点的建立:

struct Node
{
    int data;//数据域
    Node *next;//指针域
};

单链表的节点删除

1)单链表仅含一个节点,删除头节点

head=NULL;
delete head;

  简单明了,将头节点设为NULL(即为空),不能忘了delete!

2)单链表含至少两个节点,删除头节点

ListNode*p=head;
head=head->next;
delete p;

注意先将原head保存,用于delete。

3)单链表含至少两个节点,删除非头节点

ListNode*p=head;
while(p->next!=DelNode)
    p=p->next;
p->next=DelNode->next;
delete DelNode;

根据上述运算

易得题解代码

class Solution {
public:
    //删除头节点
    ListNode* removeElements(ListNode* head, int val) {
        //判断头节点是否为空且值为val
        while(head!=NULL&&head->val==val){
            ListNode*p=head;//设定探测指针p
            head=head->next;//探测指针前进
            delete p;//删除节点
        }
        ListNode*cur=head;//设定cur指针,用于在遍历链表是指向当前位置
        /*提出循环条件cur不能后是最后两个节点,
        与"if(cur!=NULL&&cur->next!=NULLL)"遥遥相对*/
        while(cur!=NULL&&cur->next!=NULL){
            //
            if(cur->next->val==val){
                ListNode*p=cur->next;
                cur->next=p->next;//非头结点删除的操作
                delete p;
            }else{
                cur=cur->next;
            }
        
        }
        return head;
    }
};

 

该题涵盖了链表的所有基本操作,把操作填进对应的函数就行。

(设置虚拟头节点dummyhead)题解代码:

class MyLinkedList {
public:
    // 定义链表节点结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    // 初始化链表
    MyLinkedList() {
        _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        _size = 0;
    }

    // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while(index--){ // 如果--index 就会陷入死循环
            cur = cur->next;
        }
        return cur->val;
    }

    // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }

    // 在链表最后面添加一个节点
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
    // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
    // 如果index大于链表的长度,则返回空
    // 如果index小于0,则在头部插入节点
    void addAtIndex(int index, int val) {

        if(index > _size) return;
        if(index < 0) index = 0;        
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
    void deleteAtIndex(int index) {
        if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur ->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        //delete命令指示释放了tmp指针原本所指的那部分内存,
        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
        tmp=nullptr;
        _size--;
    }

    // 打印链表
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;

};

 简单来说,就是对原头节点进行去特殊化。

 

法一双指针法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *temp;
        ListNode *cur=head;
        ListNode *pre=NULL;
        
        while(cur){
            temp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }
};

 注意pre,cur,temp三个的先后顺序就行。

法二递归

class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

};

标签:index,head,ListNode,cur,随想录,Day3,next,打卡,节点
From: https://blog.csdn.net/2401_86177347/article/details/143064457

相关文章

  • 打卡信奥刷题(069)用C++工具信奥P11076[普及组/提高] 「FSLOI Round I」单挑
    「FSLOIRoundI」单挑题目背景Englishstatement.YoumustsubmityourcodeattheChineseversionofthestatement.小F和小S经常进行篮球单挑,但小S总是被盖帽。题目描述每次单挑的结果一定是小F获胜或者小S获胜,不存在平局的情况。由于小F和小S实......
  • 代码随想录|二叉树part 03
    求普通二叉树的节点数量要点:将子节点的个数记录到父节点,使用后序遍历classSolution{public:intmaxDepth(TreeNode*root){if(root==NULL)return0;intleft1=maxDepth(root->left);intright1=maxDepth(root->right);intnum=......
  • 代码随想录|二叉树part 02
    翻转二叉树要点:指针交换优先利用前序或后序遍历,若采用中序遍历(则两次采用遍历左子树)classSolution{public:TreeNode*invertTree(TreeNode*root){if(root==NULL)returnroot;swap(root->left,root->right);invertTree(root->left);......