初识链表

链表的原理

链表

链表——属于线性表,元素与元素之间有相对的顺序,有头部\尾部,还有当前结点cur,前驱结点prev,后继结点next。
每个结点是为了组织链表而引入的一个结构,出来保存的元素外,还会保存指向下一个结点的引用。
head是一个链表的头结点,通过head我们可以找到所有的结点,目前我们可以用头结点来代表一整条链表。
在这里插入图片描述

实现

1、结点的定义:

class Node {
    int val;//保存元素
    Node next;//指向下一个节点的引用,尾结点的next==null
}

2、头结点:

Node head=...//当链表的头结点为null,表示头结点不存在。还可以理解为,没有头结点的链表,即一个空链表。
Node head = null;

用引用和对象的知识理解

(结点中有许多.next…看来看去就绕晕了,我们可以借助引用和对象来理解,更好接受)

1 Node P = ...; //p是一条链表中的某个结点
2 Node q = ...; //q是一条链表中的某个结点

在这里插入图片描述
在上面的情况下,画图表现变化:
1、p = q;
在这里插入图片描述
2、p = q.next;
在这里插入图片描述
3、p.next = q;
在这里插入图片描述
4、p.next = q.next;
在这里插入图片描述
总结:
我们会发现,左边和右边都存在.next,绕着绕着就把人绕晕了,对于这种情况,我们可以把等号左边去找引用,等号右边去找对象
简单说就是 左引用,右对象,这样理解。

链表具体实现

结点的定义

class Node {
    int val;//保存元素
    Node next;//指向下一个节点的引用,尾结点的next==null

    @Override
    public String toString() {
        return "Node{" + "val=" + val + '}';
    }
}

链表的创建

        Node n1 = new Node();
        Node n2 = new Node();
        Node n3 = new Node();
        Node n4 = new Node();

        n1.val = 1;
        n2.val = 2;
        n3.val = 3;
        n4.val = 4;

        n1.next = n2;
        n2.next = n3;
        n3.next = n4;
        n4.next = null;

        Node head = n1;

链表的遍历

遍历每个元素和计算链表中元素个数

        Node head = n1;
        int count = 0;
        Node cur = head;
        while (cur != null) {

            System.out.println(cur.val);
            cur = cur.next;
            count++;
        }
        System.out.println(count);

找到最后一个结点

        Node cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }
        System.out.println(cur.val);
    }

找到倒数第二个结点

        //找到倒数第二个结点
        Node cur = head;
        while (cur.next.next != null) {
            cur = cur.next;
        }
        System.out.println(cur.val);
    }

找到第n个结点

        //找到第n个结点

        int n = 2;
        Node ncur = head;
        for (int i = 1; i < n; i++) {
            ncur = ncur.next;
        }
        System.out.println(ncur.val);

找到链表中是否包含某个元素

        Node cur = head;
        while (cur != null) {
            if (cur.val == target) {
                //找到了
                System.out.println("找到了");
            }
            cur = cur.next;
        }
        System.out.println("没找到");

链表的插入和删除

给定前驱结点后的插入

        Node prev = n2;
        Node node = new Node();
        node.val = 6;

        node.next = prev.next;
        prev.next = node;

给定前驱结点后的删除

        Node prev = n2;
        prev.next = prev.next.next;

头插

        Node node=new Node();
        node.val=12;
        
        node.next=head;
        head=node;  

头删

        //头删
        if (head == null) {
            throw new RuntimeException("链表为空");
        }
        head = head.next;

尾插

        //链表为空,直接插入
        if (head == null) {
            Node node = new Node();
            node.val = 1;
        }
        //链表不为空
        Node last = head;
        while (last.next != null) {
            last = last.next;
        }
        Node node = new Node();
        node.val = 12;
        last.next = node;

尾删

        //尾删
        if (head == null) {
            throw new RuntimeException("链表为空");
        }
        //链表不为空只有一个节点
        if (head.next == null) {
            head.next=null;
        }
        Node last = head;
        while (last.next.next != null) {
            last = last.next;
        }
        last.next = null;

总结:

我们发现链表里面有许多的 (.next),左边有,右边也有,有的代表着引用,有的代表着对象。
我们可以把等号左边去找引用,等号右边去找对象
简单说就是 左引用,右对象,这样理解。

对于数据结构的问题,我们真的需要多多的去理解,并且多画图,借助图像理解数据结构的具体逻辑。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
这道题目是要求我们实现链表的基本操作,包括创建链表、插入节点、删除节点、遍历链表等。以下是一个简单的链表实现代码示例: ```c++ #include <iostream> using namespace std; // 定义链表节点结构体 struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; // 创建链表 ListNode* createList(int nums[], int n) { if (n == 0) return NULL; ListNode *head = new ListNode(nums[0]); ListNode *cur = head; for (int i = 1; i < n; i++) { cur->next = new ListNode(nums[i]); cur = cur->next; } return head; } // 插入节点 void insertNode(ListNode *&head, int pos, int val) { if (pos < 0) return; if (pos == 0) { ListNode *newNode = new ListNode(val); newNode->next = head; head = newNode; return; } ListNode *cur = head; while (cur && pos > 1) { cur = cur->next; pos--; } if (cur) { ListNode *newNode = new ListNode(val); newNode->next = cur->next; cur->next = newNode; } } // 删除节点 void deleteNode(ListNode *&head, int pos) { if (pos < 0) return; if (pos == 0) { ListNode *delNode = head; head = head->next; delete delNode; return; } ListNode *cur = head; while (cur && pos > 1) { cur = cur->next; pos--; } if (cur && cur->next) { ListNode *delNode = cur->next; cur->next = delNode->next; delete delNode; } } // 遍历链表 void traverseList(ListNode *head) { while (head) { cout << head->val << " "; head = head->next; } cout << endl; } int main() { int nums[] = {1, 2, 3, 4, 5}; int n = sizeof(nums) / sizeof(int); ListNode *head = createList(nums, n); traverseList(head); insertNode(head, 2, 6); traverseList(head); deleteNode(head, 3); traverseList(head); return 0; } ``` 在上面的代码中,我们定义了一个 `ListNode` 结构体作为链表节点,包括节点值 `val` 和指向下一个节点的指针 `next`。同时,我们实现了创建链表、插入节点、删除节点和遍历链表等基本操作。在使用链表时,我们可以先通过 `createList` 函数创建一个链表,然后对链表进行插入、删除和遍历操作。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无赖H4

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值