【算法与数据结构】707、LeetCode设计链表

文章目录

  • 一、题目
  • 二、设计链表
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

【算法与数据结构】707、LeetCode设计链表_第1张图片

【算法与数据结构】707、LeetCode设计链表_第2张图片

二、设计链表

  思路分析:这里我将的成员函数放在类外实现了,这样链表类看起来更加简洁,方便大家学习链表的结构,主要包含:节点类结构体,构造函数(构造函数也可以放在类外实现),成员函数和成员变量类的成员函数实现主要有两种,一种是类内实现,一种是类外实现,类外实现需要在类内写声明,然后在类外写实现。构造函数初始化一个虚假头结点和链表大小。关于虚假头结点,可以参考【算法与数据结构】203、LeetCode移除链表元素。
  链表类如下

// 链表类
class MyLinkedList {
public:   
    // 定义链表节点类结构体
    struct LinkNode {
        int val;
        LinkNode* next;
        LinkNode() : val(0), next(NULL) {};
        LinkNode(int input_val) : val(input_val), next(NULL) {};
        LinkNode(int input_val, LinkNode* input_next) : val(input_val), next(input_next) {};
    };
    // 构造函数
    MyLinkedList() {
        _FakeNode = new LinkNode(0);    // 虚假头结点
        _size = 0;
    }
// 成员函数
    int get(int index);
    void addAtHead(int val);
    void addAtTail(int val);
    void addAtIndex(int index, int val);
    void deleteAtIndex(int index);
    void ChainGenerator(int arr[], int len);
    void LinkListPrint(string str);
// 成员变量
private:
    int _size;
    LinkNode* _FakeNode;
};

  讲完整体构造,然后将各个部分。
  首先是get函数:进入链表首先判断index是否合法,然后链表从虚假头结点出发,利用index,当找到目标索引时,cur就指向这个值,index自减归于0退出循环

int MyLinkedList::get(int index) { 
    if (index > (_size - 1) || index < 0) return -1;
    LinkNode* cur = _FakeNode->next; // 头结点
    while (index--) {
        cur = cur->next;
    }
    return cur->val;
}

  addAtHead函数:这个函数比较简单,我们新建一个节点,指向虚节点的下一个节点(也就是插入之前的头结点),然后让虚节点指向新建节点,最后链表大小+1。

void MyLinkedList::addAtHead(int val) {
    LinkNode* pNewNode = new LinkNode(val, _FakeNode->next);
    _FakeNode->next = pNewNode;
    _size++;
}

  addAtTail函数:addTail函数需要遍历这个链表,找到尾节点,复杂度是 O ( n ) O(n) O(n),让尾节点指向新建节点即可。

void MyLinkedList::addAtTail(int val) {
    LinkNode* pNewNode = new LinkNode(val);
    LinkNode* cur = _FakeNode;
    while (cur->next != NULL) {
        cur = cur->next;
    }
    cur->next = pNewNode;
    _size++;
}

  addAtIndex函数:前两个函数都可以用这个函数实现,在这个函数中,首先根据题目条件判断index是否合法,令cur指针等于虚节点,同样使用index找到插入位置的上一个节点,然后就是链表的插入操作。

void MyLinkedList::addAtIndex(int index, int val) {   
    if (index > _size) return;
    if (index < 0) index = 0;
    LinkNode* cur = _FakeNode; // 虚结点 
    // 需要断开上一一个阶段的链接,从插入位置的上一个索引开始处理
    while (index--) {
        cur = cur->next;
    }
    LinkNode* pNewNode = new LinkNode(val, cur->next);
    cur->next = pNewNode;
    _size++;
}

  deleteAtIndex函数:这个函数可以参考【算法与数据结构】203、LeetCode移除链表元素。

void MyLinkedList::deleteAtIndex(int index) {     
    if (index > (_size - 1) || index < 0) return;
    LinkNode* cur = _FakeNode; // 头结点
    // 需要断开上一一个阶段的链接
    while (index--) {
        cur = cur->next;
    }
    LinkNode* tmp = cur->next;
    cur->next = cur->next->next;
    delete tmp;
    tmp = NULL;
    _size--;
}

  ChainGenerator函数和LinkListPrint函数:除了题目要求的函数以外,我还写了数组生成链表函数,以及链表打印函数。这两个函数在main函数中调用,方便调试。

void MyLinkedList::ChainGenerator(int arr[], int len) {
    if (_FakeNode->next != NULL) return;
    LinkNode* head = new LinkNode(arr[0], NULL);
    LinkNode* p = head;
    for (int i = 1; i < len; i++) {
        LinkNode* pNewNode = new LinkNode(arr[i], NULL);
        p->next = pNewNode; // 上一个节点指向这个新建立的节点
        p = pNewNode; // p节点指向这个新的节点
    }
    _FakeNode->next = head;
    _size = len;
}
void MyLinkedList::LinkListPrint(string str) {
    cout << str << endl;
    LinkNode* cur = _FakeNode;
    while (cur->next != NULL) {
        cout << cur->next->val << ' ';
        cur = cur->next;
    }
    cout << endl;
}

三、完整代码

# include 
using namespace std;

// 链表类
class MyLinkedList {
public:   
    // 定义链表节点类结构体
    struct LinkNode {
        int val;
        LinkNode* next;
        LinkNode() : val(0), next(NULL) {};
        LinkNode(int input_val) : val(input_val), next(NULL) {};
        LinkNode(int input_val, LinkNode* input_next) : val(input_val), next(input_next) {};
    };
    // 构造函数
    MyLinkedList() {
        _FakeNode = new LinkNode(0,NULL);    // 虚假头结点
        _size = 0;
    }
// 成员函数
    int get(int index);
    void addAtHead(int val);
    void addAtTail(int val);
    void addAtIndex(int index, int val);
    void deleteAtIndex(int index);
    void ChainGenerator(int arr[], int len);
    void LinkListPrint(string str);
// 成员变量
private:
    int _size;
    LinkNode* _FakeNode;
};

// 类外实现链表的成员函数
int MyLinkedList::get(int index) { 
    if (index > (_size - 1) || index < 0) return -1;
    LinkNode* cur = _FakeNode->next; // 头结点
    while (index--) {
        cur = cur->next;
    }
    return cur->val;
}

void MyLinkedList::addAtHead(int val) {
    LinkNode* pNewNode = new LinkNode(val, _FakeNode->next);
    _FakeNode->next = pNewNode;
    _size++;
}

void MyLinkedList::addAtTail(int val) {
    LinkNode* pNewNode = new LinkNode(val);
    LinkNode* cur = _FakeNode;
    while (cur->next != NULL) {
        cur = cur->next;
    }
    cur->next = pNewNode;
    _size++;
}

void MyLinkedList::addAtIndex(int index, int val) {   
    if (index > _size) return;
    if (index < 0) index = 0;
    LinkNode* cur = _FakeNode; // 虚结点 
    // 需要断开上一一个阶段的链接,从插入位置的上一个索引开始处理
    while (index--) {
        cur = cur->next;
    }
    LinkNode* pNewNode = new LinkNode(val, cur->next);
    cur->next = pNewNode;
    _size++;
}

void MyLinkedList::deleteAtIndex(int index) {     
    if (index > (_size - 1) || index < 0) return;
    LinkNode* cur = _FakeNode; // 头结点
    // 需要断开上一一个阶段的链接
    while (index--) {
        cur = cur->next;
    }
    LinkNode* tmp = cur->next;
    cur->next = cur->next->next;
    delete tmp;
    tmp = NULL;
    _size--;
}

void MyLinkedList::ChainGenerator(int arr[], int len) {
    if (_FakeNode->next != NULL) return;
    LinkNode* head = new LinkNode(arr[0], NULL);
    LinkNode* p = head;
    for (int i = 1; i < len; i++) {
        LinkNode* pNewNode = new LinkNode(arr[i], NULL);
        p->next = pNewNode; // 上一个节点指向这个新建立的节点
        p = pNewNode; // p节点指向这个新的节点
    }
    _FakeNode->next = head;
    _size = len;
}

void MyLinkedList::LinkListPrint(string str) {
    cout << str << endl;
    LinkNode* cur = _FakeNode;
    while (cur->next != NULL) {
        cout << cur->next->val << ' ';
        cur = cur->next;
    }
    cout << endl;
}

int main()
{
    int arr[] = { 2, 3};
    int len = sizeof(arr) / sizeof(int);
    MyLinkedList m1;
    m1.ChainGenerator(arr, len);
    m1.LinkListPrint("打印链表:");
    m1.addAtHead(1);
    m1.addAtTail(5);
    m1.LinkListPrint("打印链表:");
    m1.addAtIndex(3, 4);
    m1.addAtIndex(5, 666);
    m1.LinkListPrint("打印链表:");
    m1.deleteAtIndex(5);
    m1.LinkListPrint("打印链表:");
    int val1 = m1.get(0);
    cout << "目标索引的值:" << val1 << endl;

    system("pause");
    return 0;
}

end

你可能感兴趣的:(算法,算法)