数据结构-链表&Leetcode链表简单题

链表简介

链表是一种经典的数据结构,用于存储线性数据结构,如列表、队列和栈。它是由一系列节点组成的,每个节点都包含一个存储指针和一个数据变量。指针指向下一个节点,最后一个节点指向NULL。
在C++中实现链表需要定义节点类。该类包含两个成员变量:一个指向下一个节点的指针和一个数据变量。然后定义链表类,该类包含一个指向链表头的指针和一些成员函数。
一个指针域一个数据域,指针域指向下一节点的数据域;

代码

//list.h
#pragma once
#include<vector>
#include<iostream>
using namespace std;
struct Node{
    
    
    Node *next;
    int val;
    //结构体构造
    Node(int val){
    
    
        next = nullptr;
        this->val = val;
    }
};

class List{
    
    
    pHead = nullptr;
    pTail = nullptr;
public:
    List();
    List(std::vector<int> vec);
    void printList();
    Node* getHead();
    Node* getTail();
    void addNode(int val);
    bool delNode(int val);
    bool updataNode(int res ,int des);
    Node* findNode(int val);
};
//list.cpp
#include "List.h"
List::List(){
    
    }

List::List(std::vector<int> vec){
    
    
    for (int i = 0; i < vec.size(); i++){
    
    
    	// 通过vec 创建新节点,node存的是节点的地址
        Node *node = new Node(vec[i]);
         //如果创建的节点是链表的第一个节点那么让phead 和 ptail 都指向这个节点
        if (pHead == nullptr){
    
    
            pHead = node;
            pTail = node;
        }
        else{
    
    
        	//把新节点加入到链表
            pTail->next = node;
            //移动ptail指针指向最后一个节点,也就是新节点node
            pTail = node; 
        }
    }
}

void List::printList(){
    
    
    Node *p = pHead;
    while (p){
    
    
        std::cout << p->val << " ";
        p = p->next;
    }
}

Node* List::getHead(){
    
    
    return pHead;
}
Node* List::getTail(){
    
    
    return pTail;
}

void List::addNode(int val){
    
    
    Node *node = new Node(val);
    pTail->next = node;
    pTail = node;
}

bool List::delNode(int val){
    
    
    Node* fast = pHead;
    Node* slow = nullptr;
    while (fast!=nullptr){
    
    
        if (fast->val == val){
    
    
            if (fast == pHead){
    
    
                pHead = pHead->next;
            }
            else{
    
    
                slow->next = fast->next;
            }
            return true;
        }
        slow = fast;
        fast = fast->next;
    }
    return false;
}

bool List::updataNode(int res, int des){
    
    
    Node * p =findNode(res);
    if (p){
    
    
        p->val = des;
        return true;
    }
    return false;
}

Node* List::findNode(int val){
    
    
    Node *p = pHead;
    while (p){
    
    
        if (p->val == val){
    
    
            return p;
        }
        p = p->next;
    }
    return nullptr;
}
//main.cpp
#include"List.h"
using namespace std;

int main(){
    
    
    vector<int> vec = {
    
    1,2,3,4,5};
    List list(vec);
    list.printList();
    return 0;
}

头插法和尾插法

链表的头插法和尾插法主要指的是在不同的位置插入节点。头插法指将新节点插入链表的头部,而尾插法指将新节点插入链表的尾部。
下面是基于上一个例子修改后实现链表头插法和尾插法的示例代码:

#include <iostream>
using namespace std;

// 链表节点类
class Node {
    
    
public:
    int data;
    Node* next;
    Node(int data) : data(data), next(nullptr) {
    
    }
};

// 链表类
class LinkedList {
    
    
private:
    Node* head;

public:
    LinkedList() : head(nullptr) {
    
    }

    // 尾插法插入节点
    void appendNode(int data) {
    
    
        Node* newNode = new Node(data);
        if (head == nullptr) {
    
    
            head = newNode;
        } else {
    
    
            Node* cur = head;
            while (cur->next != nullptr) {
    
    
                cur = cur->next;
            }
            cur->next = newNode;
        }
    }

    // 头插法插入节点
    void prependNode(int data) {
    
    
        Node* newNode = new Node(data);
        if (head == nullptr) {
    
    
            head = newNode;
        } else {
    
    
            newNode->next = head;
            head = newNode;
        }
    }

    // 删除指定数据节点
    void deleteNode(int data) {
    
    
        if (head == nullptr) {
    
    
            return;
        }

        Node* cur = head;
        Node* prev = nullptr;

        while (cur != nullptr && cur->data != data) {
    
    
            prev = cur;
            cur = cur->next;
        }

        if (cur == nullptr) {
    
    
            return;
        }

        if (prev == nullptr) {
    
    
            head = cur->next;
        } else {
    
    
            prev->next = cur->next;
        }

        delete cur;
    }

    // 打印链表
    void printList() {
    
    
        Node* cur = head;
        while (cur != nullptr) {
    
    
            cout << cur->data << " ";
            cur = cur->next;
        }
        cout << endl;
    }
};

int main() {
    
    
    LinkedList linkedList;
    // 尾插法插入节点
    linkedList.appendNode(1);
    linkedList.appendNode(3);
    linkedList.appendNode(5);
    linkedList.appendNode(7);
    linkedList.printList();  // 输出: 1 3 5 7
    // 头插法插入节点
    linkedList.prependNode(2);
    linkedList.prependNode(4);
    linkedList.printList();  // 输出: 4 2 1 3 5 7
    // 删除指定节点
    linkedList.deleteNode(3);
    linkedList.printList();  // 输出: 4 2 1 5 7
    linkedList.deleteNode(4);
    linkedList.printList();  // 输出: 2 1 5 7
    return 0;
}

在这个示例代码中,我们定义了appendNode方法和prependNode方法来分别实现链表的尾插法和头插法。此外,我们还定义了deleteNode方法来删除链表中给定数据的节点。在主函数中,我们首先使用尾插法插入一些节点,然后使用头插法插入一些节点,并最终删除一些节点并输出链表。

Leetcode链表简单题

合并两有序链表

class Solution {
    
    
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
    
    
        //创建虚拟头节点pHead和pTail
        ListNode* pHead = new ListNode(0);
        ListNode* ptail = pHead;
        //循环  判断链表是否为空
        while (list1 != nullptr && list2 != nullptr) {
    
    
            //比较list1和list2两个节点的大小
            if (list1->val < list2->val) {
    
    
                //连接较小的链表
                ptail->next = list1;
                //list1向前移动
                list1 = list1->next;
            }
                  else {
    
    
                //连接较小的链表
                ptail->next = list2;
                //list2向前移动
                list2 = list2->next;
            }
            //pTail向前移动
            ptail = ptail->next;
        }
        //判断list1和list2两个链表是否为空,不为空的那组pTail持续向前移动
        ptail->next = list1 == nullptr ? list2 : list1;
        return pHead->next;
    }
};

删除排序链表中的重复元素

class Solution {
    
    
public:
    ListNode* deleteDuplicates(ListNode* head) {
    
    
        if (!head) return head;
        ListNode* pHead = head;
        while (pHead->next) {
    
    
            if (pHead->val == pHead->next->val) {
    
    
                pHead->next = pHead->next->next;
            }
            else {
    
    
                pHead = pHead->next;
            }
        }
        return head;
    }
};

移除链表元素

class Solution {
    
    
public:
    ListNode* removeElements(ListNode* head, int val) {
    
    
        //判断是否为空链表或者链表一个数且同为val
        while (head && head->val == val) {
    
    
            head = head->next;
        }
        //定义快慢指针(双指针)
        ListNode* fast = head;
        ListNode* slow = head;
        //执行
        while (fast) {
    
    
            if (fast->val == val) {
    
    
                //移除链表元素
                slow->next = fast->next;
            }
            else {
    
    
                slow = fast;
            }
            //快指针指向下一个地址
            fast = fast->next;
        }
        return head;
    }
};

反转链表

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

回文链表

class Solution {
    
    
public:
    bool isPalindrome(ListNode* head) {
    
    
        if (head == nullptr || head->next == nullptr) {
    
    
            return true;
        }
        //快慢指针找到中间节点
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
    
    
            slow = slow->next;
            fast = fast->next->next;
        }
        //反转后半部分链表
        ListNode* pre = nullptr;
        ListNode* cur = slow->next;
        while (cur != nullptr) {
    
    
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        //比较前半部分和反转后的后半部分链表
        ListNode* p1 = head;
        ListNode* p2 = pre;
        while (p2 != nullptr) {
    
    
            if (p1->val != p2->val) {
    
    
                return false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }
        return true;
    }
};

猜你喜欢

转载自blog.csdn.net/m0_58235748/article/details/131166855
今日推荐