Java数据结构与算法笔记——单向链表和双端链表

链表

链表是一种常见的基础数据结构,是一种线性表,但是链表不会按线性的顺序存储数据,而是在每个节点里存到下一个节点的指针

优点:
使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分地利用计算机内存空间,实现灵活的内存动态管理。

缺点:
链表失去了数组随机读取的优点(没有下标),同时链表由于增加了节点的指针域,空间开销比较大。

单向链表

单向链表简介

单向链表是链表中结构最简单的。
一个单链表的节点(Node)分为两个部分,第一部分保存或者显示关于节点的信息,另一个部分存储下一个节点的地址。
最后一个节点存储地址的部分指向空值。链表有一个头结点。
在这里插入图片描述
查找:
从第一个节点开始遍历
删除:
删除节点,把上一个节点的指针指向下一节点(速度比数组快)
插入:
在头部插入

java实现单向链表

package link;

public class SingleLinkTest {
    public static void main(String[] args) {
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.addHead('A');
        singleLinkedList.addHead('B');
        singleLinkedList.addHead('C');
        singleLinkedList.addHead('D');

        //打印链表
        singleLinkedList.display();

        System.out.println(singleLinkedList.delete('A'));

        singleLinkedList.display();
        System.out.println(singleLinkedList.isEmpty());

        System.out.println(singleLinkedList.deleteHead());


    }
}

//封装单向链表的类
class SingleLinkedList{
    private int size; //链表的节点数
    private Node head; // head是头结点的指针,引入了一个新类型,node

    //构造方法
    public SingleLinkedList(){
        size = 0;
        head = null;
    }

    //向链表中添加节点(添加到头部)
    public Object addHead(Object data){
        Node newNode = new Node(data);
        if(size == 0){
            //空链表
            head = newNode;
        }else {
            //非空链表
            newNode.next = head;
            head = newNode;
        }
        size ++;
        return newNode;
    }

    //链表删除头结点,默认链表中是有节点的
    public Object deleteHead(){
        Object obj = head.data;
        head = head.next;
        size--;
        return obj;
    }

    //查找指定数据所对应的节点对象
    public Node find(Object data){
        Node curent = head;
        int tmpSize = size;
        while (tmpSize > 0){
            if (data.equals(curent.data)){
                //找到了对象
                return curent;
            }else {
                curent = curent.next;
            }
            tmpSize--;
        }
        return null; //如果找不到
    }

    //判断链表是不是空链表
    public boolean isEmpty(){
        return size==0;
    }

    //删除指定节点,删除成功返回true,失败返回false
    public boolean delete(Object value){
        if(isEmpty()){
            //空表
            return false;
        }

        //不是空表
        Node current = head;
        Node previous = head;//上一个变量
        while (!value.equals(current.data)){
            if (current.next == null){
                //已经扫描到了尾结点,且没找到数据
                return false;
            }else{
                //还没到尾结点
                previous = current;
                current = current.next;
            }
        }
        // 循环终止了,还会继续执行下面的语句,证明已经找到了要找的节点
        //删除找到的节点
        if(current == head){
            head = head.next;
            size --;
        }else{
            previous.next = current.next;
            size --;
        }
        return true;
    }

    //遍历输出所有node信息
    public void display(){
        if (size>0){
            //不是空的
            Node current = head;
            int tmpSize = size;
            if (tmpSize == 1){
                System.out.println("[" + head.data + "]");
                return; // 结束掉方法
            }
            while (tmpSize>0){
                if (current == head){
                    System.out.print("[" + current.data + "->");
                }else if(current.next == null){
                    //最后一个节点
                    System.out.print(current.data + "]");
                }else {
                    System.out.print(current.data + "->");
                }
                tmpSize --;
                current = current.next;
            }
            System.out.println();//输出一个换行符
        }else {
            //空列表
            System.out.println("[]");
        }
    }

    //定义一个私有类
    private class Node{
        private Object data; //封装在节点里的数据
        private Node next; //指针,指向下一个节点

        //构造方法
        public Node(Object data){
            this.data = data;

        }

        @Override
        public String toString() {
            return "Node [data=" + data + ", next=" + next + "]";
        }
    }
}

双端链表

双端链表简介

对于单向链表,我们如果想在尾部添加一个节点,那么必须从头部一直遍历到尾部,找到尾结点,然后在尾结点后面插入一个节点。
这样操作很慢,如果我们在设计链表的时候多个对尾结点的引用,那么会简单很多

java实现双端链表

package link;

public class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList link = new DoubleLinkedList();
        link.addHead(1);
        link.addHead(0);
        link.addTail(2);
        link.addTail(3);
        link.addTail(2);
        link.display();

        link.delete(2);
        link.display();
        System.out.println(link.deleteHead());
        link.display();

        while(!link.isEmpty()){
            System.out.println(link.deleteTail());
        }

    }
}

class DoubleLinkedList{
    private int size; //链表的节点数
    private Node head; // head是头结点的指针,引入了一个新类型,node
    private Node tail; //指向尾结点的指针

    //构造方法
    public DoubleLinkedList(){
        size = 0;
        head = null;
        tail = null;
    }

    //向链表中添加节点(添加到头部)
    public Object addHead(Object data){
        Node newNode = new Node(data);
        if(size == 0){
            //空链表
            head = newNode;
            tail = newNode;
        }else {
            //非空链表
            newNode.next = head;
            head = newNode;
        }
        size ++;
        return newNode;
    }

    //添加尾结点
    public Object addTail(Object data){
        Node newNode = new Node(data);
        if(size == 0) {
            //空链表
            head = newNode;
            tail = newNode;
        }else {
            tail.next = newNode;
            tail = newNode;
        }
        size ++;
        return newNode;
    }

    //链表删除头结点
    public Object deleteHead(){
        Object obj = null;
        if(size == 0){
            //空链表
            return obj;
        }else if(size == 1){
            //链表中只有一个节点
            obj = head.data;
            head = null;
            tail = null;
            size --;
        }else{
            obj = head.data;
            head =head.next;
            size --;
        }

        return obj;
    }

    //删除尾部节点
    public Object deleteTail(){
        Object obj = null;
        if(size == 0){
            //空链表
            return obj;
        }else if(size == 1) {
            //链表中只有一个节点
            obj = tail.data;
            head = null;
            tail = null;
            size --;
        }else {
            obj = tail.data;
//            int tmp = 1;
            Node tmpNode = head;
//            while (tmp<size-1){
//                tmpNode = tmpNode.next;
//                tmp ++;
//            }

            while (tmpNode.next != tail){
                tmpNode = tmpNode.next;
            }

            tail = tmpNode;
            tail.next = null;
            size --;
        }

        return obj;
    }

    //判断链表是不是空链表
    public boolean isEmpty(){
        return size==0;
    }

    //删除指定节点,删除成功返回true,失败返回false
    public boolean delete(Object value){
        if(isEmpty()){
            //空表
            return false;
        }

        //不是空表
        Node current = head;
        Node previous = head;//上一个变量
        while (!value.equals(current.data)){
            if (current.next == null){
                //已经扫描到了尾结点,且没找到数据
                return false;
            }else{
                //还没到尾结点
                previous = current;
                current = current.next;
            }
        }
        // 循环终止了,还会继续执行下面的语句,证明已经找到了要找的节点
        //删除找到的节点
        if(size == 1){
            head = null;
            tail = null;
        }else if(current == head){
            head = head.next;
        }else if(current == tail){
            previous.next = null;
            tail = previous;
        }else {
            previous.next = current.next;
        }
        size --;
        return true;
    }

    //遍历输出所有node信息
    public void display(){
        if (size>0){
            //不是空的
            Node current = head;
            int tmpSize = size;
            if (tmpSize == 1){
                System.out.println("[" + head.data + "]");
                return; // 结束掉方法
            }
            while (tmpSize>0){
                if (current == head){
                    System.out.print("[" + current.data + "->");
                }else if(current.next == null){
                    //最后一个节点
                    System.out.print(current.data + "]");
                }else {
                    System.out.print(current.data + "->");
                }
                tmpSize --;
                current = current.next;
            }
            System.out.println();//输出一个换行符
        }else {
            //空列表
            System.out.println("[]");
        }
    }

    //获取节点个数
    public int getSize(){
        return size;
    }

    //定义一个私有类
    private class Node{
        private Object data; //封装在节点里的数据
        private Node next; //指针,指向下一个节点

        //构造方法
        public Node(Object data){
            this.data = data;
        }

        @Override
        public String toString() {
            return "Node [data=" + data + ", next=" + next + "]";
        }
    }

}

基于双端链表实现队列

队列:队尾插入,队头删除。先进先出。

package link;

public class QueueDoubleLinkedListTest {
    public static void main(String[] args) {
        QueueDoubleLinkedList queueDoubleLinkedList = new QueueDoubleLinkedList();
        queueDoubleLinkedList.insert(1);
        queueDoubleLinkedList.insert(2);
        queueDoubleLinkedList.insert(3);
        queueDoubleLinkedList.insert(4);

        queueDoubleLinkedList.display();

        System.out.println(queueDoubleLinkedList.delete());
        queueDoubleLinkedList.display();
        System.out.println(queueDoubleLinkedList.isEmpty());
        System.out.println(queueDoubleLinkedList.getSize());
    }
}

class QueueDoubleLinkedList{
    private DoubleLinkedList doubleLinkedList;

    public QueueDoubleLinkedList(){
        doubleLinkedList = new DoubleLinkedList();
    }

    //插入(链表尾部插入)
    public void insert(Object data){
        doubleLinkedList.addTail(data);
    }

    //删除(链表头部删除)
    public Object delete(){
        return doubleLinkedList.deleteHead();
    }

    //是否为空
    public boolean isEmpty(){
        return doubleLinkedList.isEmpty();
    }

    //获取队列元素个数
    public int getSize(){
        return doubleLinkedList.getSize();
    }

    //显示队列元素
    public void display(){
        doubleLinkedList.display();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值