链表学习之单链表

我的方法是,先了解链表的原理,然后书写代码

1.了解new的用法,如何开辟内存

2.如何写函数封装

3.如何遍历链表

4.如何实现函数功能

5.如何写代码,并真正了解链表如何使用

6.能独立写一个链表函数

7.能够独立写出来一个双链表 

首先就是leetcode上的水题​​​​​​203. 移除链表元素 - 力扣(LeetCode)

有两种写法,一种是非虚拟节点法

/**
 * Definition for singly-linked list.
 * 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) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //删除头结点
        while(head!=NULL&&head->val==val){
            ListNode *temp=head;
            head=temp->next;
            delete temp;
        }

        //如果不是头结
        ListNode* cur=head;
        while(head!=NULL&&cur->next!=NULL){
            if(cur->next->val==val){
                ListNode* temp=cur->next;
                cur->next=cur->next->next;
                delete (temp);
            }
            else {
                cur=cur->next;
            }
        }
        return head;


    }
};

这种写法唯一注意的地方就是是

cur->next=cur->next->next;

因为这是你的cur的指针指向的东西,是他的下一个要指向下下个节点,懂否?

cur只是一个当前的地址而已

第二种是虚拟节点的方法

可以和插入法结合起来使用,也就是形式一致

/**
 * Definition for singly-linked list.
 * 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) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //设置一个新的虚拟头结点
        ListNode *dummyhead =new ListNode(0);
        dummyhead->next=head;

        ListNode* cur=dummyhead;
        while(head!=NULL&&cur->next!=NULL){
            if(cur->next->val==val){
                ListNode* temp=cur->next;
                cur->next=cur->next->next;
                delete (temp);
            }
            else {
                cur=cur->next;
            }
        }
        head=dummyhead->next;
        delete dummyhead;
        return head;


    }
};

这一点的head!=NULL可以不要因为cur指向的第一个就是head;

记住最后一步要把链表给收回来,把头结点重新安装回去,不要忘记了链表的结构啊,会报错的

class MyLinkedList {
public:


    

  struct LinkNode {
        int val;
        LinkNode* next;
        //cpp的创建链表的一种方式
        LinkNode(int val):val(val), next(nullptr){}
    };


    //要先进行定义
    private:
    int size;
    LinkNode* dummynode;

     MyLinkedList() {
        dummynode = new LinkNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        size = 0;
    }
    
    int get(int index) {

        if(index<0||index>size-1){
            return -1;
        }
    
        //这个不需要赋予它个结构体的嘞,因为真的很不需要LinkNode * cur=new LinkNode(0);
        LinkNode* cur=dummynode->next;
        while(index--){
            cur=cur->next;

        }
        return cur->val;

    }
    
    void addAtHead(int val) {
        LinkNode *newHead=new LinkNode(val);
        //这里最好先把指针指向head以便于后面的操作,在中间插入节点,形成统一
        newHead->next = dummynode->next;
        dummynode->next=newHead;
        size++;


    }
    
    void addAtTail(int val) {
        LinkNode* LastNode=new LinkNode(val);
        LinkNode* cur=dummynode;

        //int size_num=size;
        while(cur->next!=nullptr){
            cur=cur->next;
        }
        cur->next=LastNode;
        LastNode->next=NULL;
        size++;

    }
    
    void addAtIndex(int index, int val) {
        if(index>size)return;
        if(index<0)index=0;
     LinkNode *newNode=new LinkNode(val);
     LinkNode* cur=dummynode;
     while(index--){
         cur=cur->next;
     }
     newNode->next=cur->next;
     cur->next=newNode;
     size++;
    }
    
    void deleteAtIndex(int index) {
        if(index<0||index>size-1){
            return;
        }
        LinkNode *cur=dummynode;
        while(index--){
            cur=cur->next;
        }
        LinkNode *temp=cur->next;
        cur->next=cur->next->next;
        delete temp;
        temp=nullptr;
        size--;
    }

    void printLinkList(){
        if(size=0)return ;

        LinkNode *cur=dummynode;
        while(cur->next!=NULL){
            cout<<cur->next->val;
            cur= cur->next;
        }
        cout<<endl;


    }

    
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

本题就是手搓一个链表的一些功能,实现一个动态链表,还是非常好的一个题,让我这个链表渣滓都略知1,2单向链表的用法了,建议熟练掌握,还有本题的一些关键点

1.一定要事先声明好,结构体指针,免得报错

2.一定要注意cur指向的对象,cur->next

3.一定要在脑子里建立一张链表,知道在链表增删改查的过程,脑子要很清醒,要拿笔去算,OK?脑子要灵活一点儿 

707. 设计链表 - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值