数据结构四、实现链表(链表为底层的动态栈and队列)与递归(猴子吃peach)以及单链表的递归

本文详细介绍了链表的数据结构,包括创建链表、链表的增删查改操作。通过链表实现了动态栈和队列,并探讨了递归的概念,使用递归思想解决猴子吃桃子问题以及链表操作。
摘要由CSDN通过智能技术生成

  • 数组,栈,队列底层都是静态数组
    • 靠resize解决固定容量的问题
  • 链表是真正的动态数据结构

链表描述

  • 链表
    • 数据存在节点(node)中,(Node next)指向下一个节点的引用
    • 优点:
      • 不需要处理固定容量的问题,真正的动态
      • 增删快
    • 缺点:
      • 丧失了随机访问的能力
      • 查询慢,没有索引,需要逐个查询

创建链表

1.创建一个动态链表了
public class MyLinked<T> {
   
}
2.创建一个节点(内部类)
  • 在链表中,每一个节点都有一个指针和一个数据
  • 顺便重写节点toString,方便后续调用
//链表中数据的数据结构(节点)
    private class Node {
   
        T ele;
        Node next; //指向下一个节点

        //构造方法
        public Node(T ele) {
   
            this.ele = ele;
            next = null;
        }

        public Node() {
   
            this(null);
        }

        //重写Node toString  ele是int属性的不影响,若是对象,就直接调用toString方法了
        @Override
        public String toString() {
   
            return ele.toString();
        }
    }
3.初始化链表
  • size表示链表存储元素
  • 定义链表的虚拟头结点
    • 这个相当于null,实际不存在
    • 虚拟头节点是解决在头部添加节点的特殊处理
    • 若没有虚拟头节点,一定要注意链表为空的情况
  • 链表的构造方法
    • 创建一个长度为空的链表,虚拟头节点为空
 //链表中存放元素的个数
    private int size;
    //链表的头 虚拟头节点(解决添加头结点问题)
    private Node dummyHead;

    //链表的数据结构
    public MyLinked() {
   
        size = 0;
        dummyHead = new Node(null);
    }

    //获取链表中元素的个数
    public int getSize() {
   
        return size;
    }

    //判断链表是否为空
    public boolean isEmpty() {
   
        return size == 0;
    }
4.链表的增
  • 引用上述的头节点来解决添加头部元素问题,
    • 若没有头结点,则遍历为0的位置添加头节点,只能添加到第二个位置,无法绑定,
  • 在任意位置添加节点,
    • 引入指针pre,重点也是找到待添加元素的前一个节点 pre
    • 第一步先判断链表是否为空
    • 创建一个新节点node,将待插入的值存入节点内
    • 将指针pre指向虚拟头节点
    • 然后开始遍历,找到待插入的节点的前一个节点(头节点)
    • node.next = pre.next;
      pre.next = node;
    • 新节点的后继指向待插入节点的头节点的后继
    • 待插入节点的头节点的后继指向新节点
    • 注:
      • for (int i = 0; i < index; i++) {
        pre = pre.next;
        }
      • 这里必须是小于index,只有小于 index才能确定是待插入节点的头节点
      • node.next = pre.next;
        pre.next = node;
      • 顺序不能乱
      • 顺序乱了,就变成待插入节点的头节点的后继指向新节点,新节点的后继指向自己了,就无法添加成功
//链表的头部增加节点
    public void addHead(T ele) {
   
        add(ele, 0);
    }

    //在任意位置添加节点 重点是找到待添加元素的前一个节点 pre
    public void add(T ele, int index) {
   
        if (index < 0 || index > size) {
   
            throw new IllegalArgumentException("index is error!!");
        }
        //创建一个新节点
        Node node = new Node(ele);
        Node pre = dummyHead;//待插入位置的前一个节点
        //找到待插入节点的位置
        for (int i = 0; i < index; i++) {
   
            pre = pre.next;
        }
        node.next = pre.next;
        pre.next = node;
        size++;
    }

    //在尾部添加节点
    public void addTail(T ele) {
   
        add(ele, size);
    }
5.链表遍历
  • 实际就是输出,重写toString
  • 创建一个新节点cur ,让他指向虚拟节点的后继(可以理解为是索引为0的节点)
  • 在开始进行循环,如果cur节点的后继不是空,就一直添加,为空则跳出循环
//链表的遍历 也就是打印
    @Override
    public String toString() {
   
        StringBuilder result = new StringBuilder();
        result.append("HEAD ");
        //从头节点开始遍历
        Node cur = dummyHead.next;//当前节点
        while (cur != null) {
   
            result.append(cur.ele + "--->");
            if (cur.next == null) {
   
                result.append("NULL");
            }
            cur = cur.next;
        }
        re
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值