数据结构——链表基础

链表介绍

基础概念:链表是一种数据的组织方式。其数据分散的存放在内存的不同位置,然后通过指针将这些数据串联在一起成为一个链状结构。其中数据跟指向下一个数据的指针构成链表的一个结点

/* 链表的一个节点Node */
class Node {
    int m_data;
    Node* m_next;
};
/* 链表 */
class singleLinkList {
    Node* head; // 虚拟头结点,不存储内容,仅做头结点使用,因此该结点必定不为空
    int lenth; // 链表的长度
};
链表操作

链表的常规操作包括创建跟删除链表,链表结点的增删改查等。
构造&析构函数:由于使用了虚拟头结点的方式,头结点不为空,因此需要在构造函数初始化头结点。

    // 1. 构造函数
    singleLinkList () {
        head = new Node();
        lenth = 0;
    }
    // 2. 析构函数
    ~singleLinkList () {
        Node* cur = head->m_next;
        head->m_next = NULL; // 先置空,避免异常访问
        Node* p;
        while (cur) {
            p = cur->m_next;
            delete cur;
            cur = p;
        }
        delete head;
    }

头插:往链表的头插入一个新的结点,注意在虚拟头结点之后

    // 3. 头插
    void headInsert(int data) {
        Node* newNode = new Node(data);
        newNode->m_next = head->m_next;
        head->m_next = newNode;
        lenth++;
    }

尾插:往链表的末尾插入一个新的结点

    // 4. 尾插
    void tailInsert(int data) {
        Node* newNode = new Node(data);
        Node* p = head;
        while (p->m_next) {
            p = p->m_next;
        }
        p->m_next = newNode;
        lenth++;
    }

插入数据:链表的任意位置插入,但是需要有插入的规则

    // 5. 任意位置插入
    void insert(int data) {
        Node* newNode = new Node(data);
        Node* p = head;
        while (p->m_next) {
            if (data < p->m_data) { // 此时使用一个很简单的匹配规则
                newNode->m_next = p->m_next;
                p->m_next = newNode;
                lenth++;
                break;
            }
            p = p->m_next;
        }
    }

删除结点:

    // 6. 删除
    void remove(int data) {
        Node* p = head;
        while (p->m_next) {
            if (p->m_next->m_data == data) {
                p->m_next = p->m_next->m_next;
                lenth--;
                return;
            }
            p = p->m_next;
        }
    }

几个操作里面,其中插入跟删除操作可以结合查找操作来进行。比如先查找出某个结点,然后删除该结点。查找出某个结点,然后在该结点的之后插入一个结点。

示例代码
LeetCode练习题

  1. 移除链表元素
// 该题属于链表的基本操作,删除的结点。需要注意的是内存的释放
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* p = new ListNode(0, head);
        ListNode* phead = p;
        while (p && p->next) {
            if (p->next->val == val) {
                p->next = p->next->next;
                /* 链表原结点是否未动态申请,是否需要释放。需要调整释放内存的位置
                NodeList* cur = p->next;
                delete cur;
                */
            }else {
                p = p->next;
            }
        }
        ListNode* res = phead->next;
        delete phead;
        return res;
    }
};
  1. 反转链表
// 对原链表不断使用头结点删除的同时,对新链表不断使用头插法
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* res = nullptr;
        ListNode* temp = nullptr;
        while (head) {
            temp = head->next;
            head->next = res;
            res = head;
            head = temp;
        }
        return res;
    }
};

扩展:
有序链表,循环链表,双向链表等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值