代码随想录算法训练营第三天| 203.移除链表元素、707.设计链表、206.反转链表

学习文章链接:代码随想录


一、链表基础

1.链表的类型及定义

单链表

单链表的节点由两个部分组成,一部分存放数据,另一部分存放下一个节点数据的指针,最后一个节点指向的指针为NULL。
单链表的定义:

struct Single_List_Node{
int data;
Single_List_Node *next;//Single_List_Node * 表示一个指向该结构的指针
Single_List_Node(int x):data(x),next(NULL){}//节点的构造函数,用于初始化该对象的成员变量
}

单链表的赋值:

Single_List_Node* head=new Single_List_Node(1);
Single_List_Node* second = new Single_List_Node(2); 
Single_List_Node* third = new Single_List_Node(3);  //一开始的每个节点的next指针都指向NULL

单链接的节点链接:

head->next = second;  // 将第一个节点的next指向第二个节点
second->next = third;  // 将第二个节点的next指向第三个节点

遍历并输出元素:

Single_List_Node* current = head;
while (current != NULL) {
    std::cout << current->data << " ";  // 箭头操作符 -> 用于通过指针访问结构体或类的成员,current->data 等价于 (*current).data
    current = current->next;  // 移动到下一个节点
}

双链表

双链表的节点由三个部分组成,一部分存放数据,一部分存放指向上一个节点的指针,另一部分存放指向下一个节点的指针。
双链表的定义:

struct Double_List_Node {
    int data;
    Double_List_Node *prev;  // 指向上一个节点的指针
    Double_List_Node *next;  // 指向下一个节点的指针
    Double_List_Node(int x) : data(x), prev(NULL), next(NULL) {}  // 节点的构造函数,用于初始化该对象的成员变量
};

双链表的赋值:

Double_List_Node* head = new Double_List_Node(1);
Double_List_Node* second = new Double_List_Node(2); 
Double_List_Node* third = new Double_List_Node(3);  // 一开始的每个节点的prev和next指针都指向NULL

双链表的节点链接:

head->next = second;  // 将第一个节点的next指向第二个节点
second->prev = head;  // 将第二个节点的prev指向第一个节点
second->next = third;  // 将第二个节点的next指向第三个节点
third->prev = second;  // 将第三个节点的prev指向第二个节点

遍历并输出元素(从前向后):

Double_List_Node* current = head;
while (current != NULL) {
  std::cout << current->data << " ";  // 使用箭头操作符 -> 访问结构体或类的成员
  current = current->next;  // 移动到下一个节点
}

遍历并输出元素(从后向前):

Double_List_Node* current = third;
while (current != NULL) {
 std::cout << current->data << " ";  // 使用箭头操作符 -> 访问结构体或类的成员
 current = current->prev;  // 移动到上一个节点
}

循环链表

循环链表与单链表类似,但最后一个节点的next指针指向链表的头节点,形成一个循环结构。
循环链表的定义:

struct Circular_List_Node {
    int data;
    Circular_List_Node *next;  // 指向下一个节点的指针
    Circular_List_Node(int x) : data(x), next(NULL) {}  // 节点的构造函数,用于初始化该对象的成员变量
};

循环链表的赋值:

Circular_List_Node* head = new Circular_List_Node(1);
Circular_List_Node* second = new Circular_List_Node(2); 
Circular_List_Node* third = new Circular_List_Node(3);  // 一开始的每个节点的next指针都指向NULL

循环链表的节点链接:

head->next = second;  // 将第一个节点的next指向第二个节点
second->next = third;  // 将第二个节点的next指向第三个节点
third->next = head;  // 将第三个节点的next指向第一个节点,形成循环

遍历并输出元素:

Circular_List_Node* current = head;
if (current != NULL) {
  do {
      std::cout << current->data << " ";  // 使用箭头操作符 -> 访问结构体或类的成员
      current = current->next;  // 移动到下一个节点
  } while (current != head);  // 当再次回到头节点时停止
}
}

二、203.移除链表元素

题目链接:203.移除链表元素
思路:分情况讨论,要删除的是否是头节点;当当前值为目标值时,将前一节点指针指向的地址更新为下一个节点的值的地址
需要改进的点:要删除节点、释放内存
直接从链表删除节点:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* current = head;
        while(head!=NULL&&head->val==val){
                head=head->next;
                current = head;
        }//注意的点:先处理完头指针,再往后处理
        while (current != NULL&&current->next!=NULL) {
            if(current->next->val==val){current->next=current->next->next;
            }
            else{current=current->next;}
        }
        return head;
    }
};

创建虚拟头节点:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* current = dummy;
        while (current != NULL&&current->next!=NULL) {
            if(current->next->val==val){current->next=current->next->next;
            }
            else{current=current->next;}
        }
        head=dummy->next;
        return head;
    }
};

释放内存:

ListNode* temp = node;//先将要删除的元素做个缓存
node = node->next;//由上一个节点指向当前节点的下一个节点
delete temp;//删除缓存

三、707.设计链表

题目链接:707.设计链表
思路:先定义一个链表,观察该类实现所要求功能的需要初始化的变量,定义初始空链表。在获取链表中下标为 index 的节点的值时,需要考虑index的有效性,遍历到满足条件节点时,返回节点中data值。在头部添加变量时要注意更新head的值。在尾部添加变量时要注意考虑链表长度为0的情况。添加元素和删除元素要注意index的范围,具体操作可以通过画图的方法来理解。
未设置虚拟头节点:

struct Single_List_Node{
    int data;
    Single_List_Node *next;//Single_List_Node * 表示一个指向该结构的指针
    Single_List_Node(int x):data(x),next(NULL){}//节点的构造函数,用于初始化该对象的成员变量
    };
class MyLinkedList {
public:
    Single_List_Node *head;
    int length;
    MyLinkedList() {
        head=NULL;
        length=0;
    }
    int get(int index) {
        Single_List_Node* cur=head;
        if(index<0||index>=length){
            return -1;
        }
        else{
        for(int i=0;i<index;i++){
            if(cur!=NULL){
                cur=cur->next;
            }
            else{
                return -1;
            }
        }
        return cur->data;
        }
    }
    
    void addAtHead(int val) {
        Single_List_Node* newhead=new Single_List_Node(val);
        newhead->next=head;
        head=newhead;
        length++;
    }
    
    void addAtTail(int val) {
        Single_List_Node* current = head;
        Single_List_Node* newnode=new Single_List_Node(val);
        if(length==0){
            addAtHead(val);
        }
        else{
        for (int i = 0; i < length; i++) {
            if(current->next!=NULL){current = current->next;}
        }
        current->next=newnode;
        length++;
        }
        
    }
    
    void addAtIndex(int index, int val) {
        if(index==0){
            addAtHead(val);
        }
        else if(index==length){
            addAtTail(val);
        }
        else if(index>0&&index<length){
            Single_List_Node* current = head;
            Single_List_Node* newnode=new Single_List_Node(val);
            for (int i = 0; i < index-1; i++) {
                current = current->next;
            }
            Single_List_Node* tep = current->next;
            current->next=newnode;
            newnode->next=tep;
            length++;
        }
    }
    
    void deleteAtIndex(int index) {
        if(index>=0&&index<length){
            if(index==0){
                head=head->next;
            }
            else{
                Single_List_Node* current = head;
                for (int i = 0; i < index-1; i++) {
                    current = current->next;
                }
                Single_List_Node* tep = current->next;
                current->next=current->next->next;
                delete tep;
            }
            length--;
        }
        
    }
};

四、206.反转链表

题目链接:206.反转链表
思路:考虑链表不为空的情况,定义两个指针,一个指针pre从NULL开始,另一个指针cur从head开始,cur将当前指针指向pre,然后cur向下移动,pre更新为原cur值,如此循环,直到cur为原链表的最后一个值,跳出循环后,记得将最后一个值指向pre,因为现在pre在链表的倒数第二个位置。链表为空时返回空。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre=NULL;
        ListNode* cur=head;
        if(head!=NULL){
        while(cur->next!=NULL){
            ListNode* temp= cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }
        cur->next=pre;
        head=cur;
        }
        return head;
    }
};
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值