数据结构之链表

54 阅读4分钟

一.单向链表的操作及其Java实现

单向链表(又称单链表)是链表的一种,其特点是链表的链接方向是单向的,访问链表时要从头部开始顺序读取。单向链表是链表中结构最简单的。一个单向链表的节点(Node)可分为两部分:第1部分为数据区(data),用于保存节点的数据信息;第2部分为指针区,用

于存储下一个节点的地址,最后一个节点的指针指向null

package datasStructure;

/**
 * @program: practise-model
 * @description:单链表结构
 * @author: lbw
 * @create: 2022-04-06 15:27
 **/

public class SingleLinkedList {

    private int length;//链表节点得个数
    private Node head;//头节点

    public SingleLinkedList() {
        length = 0;
        head = null;
    }

    private class Node {
        private Object data;//每个节点得数据
        private Node next;//每个节点指向下个节点得连接
        public Node(Object data) {
            this.data = data;
        }
    }
    //向链表中添加节点
    public Object addHead(Object obj) {
        Node newHead = new Node(obj);
        if (length == 0) {
            head = newHead;
        } else {
            newHead.next = head;
            head = newHead;
        }
        length++;
        return obj;
    }

    //删除单向链表数据
    public boolean delete(Object value) {
        if (length == 0) {
            return false;
        }
        Node current = head;
        Node previous = head;

        while (current.data != value) {
            if (current.next == null) {
                return false;
            } else {
                previous = current;
                current = current.next;
            }
        }
        if (current == head) {
            head = current.next;
            length--;
        } else {
            previous.next = current.next;
            length--;
        }
        return true;
    }
    //查找node的节点
    public Node find(Object obj) {
        Node current = head;
        int tempsSize = length;
        while (tempsSize > 0) {
            if (obj.equals(current.data)) {
                System.out.println("查询结果"+current.data);
                return current;
            } else {
                current = current.next;
            }
            tempsSize--;
        }
        if(current==null){
            System.out.println("查无此结果:"+obj);
        }else {
            System.out.println("查询结果:"+current.data);
        }
        return current;
    }


    public static void main(String[] args) {
        SingleLinkedList singleLinkedList=new SingleLinkedList();

        singleLinkedList.addHead("测试1");
        singleLinkedList.addHead("测试2");
        singleLinkedList.addHead("测试3");
        singleLinkedList.addHead("测试4");
        singleLinkedList.find("测试3");
        singleLinkedList.delete("测试3");
        singleLinkedList.find("测试3");
    }

}
复制代码

结果:1649235154(1).png

二.双向链表的操作及其Java实现

在双向链表的每个数据节点中都有两个指针,分别指向其直接后继和直接前驱节点。所以,从双向链表中的任意一个节点开始,都可以很方便地访问它的直接前驱节点和直接后继节点

package datasStructure;

/**
 * @program: practise-model
 * @description:
 * @author: lbw
 * @create: 2022-04-06 17:17
 **/

public class TwoWayLinkedList {
    //表示链表头
    private Node head;
    //表示链表尾
    private Node tail;
    //链表长度
    private int length;

    public TwoWayLinkedList() {
        length = 0;
        head = null;
        tail = null;
    }


    private class Node {
        //节点数据
        private Object data;
        //下一个节点
        private Node next;
        //上一个节点
        private Node prev;

        public Node(Object data) {
            this.data = data;
        }
    }

    //在链表头部增加节点
    public void addHead(Object value) {
        Node newNode = new Node(value);
        if (length == 0) {
            head = newNode;
            tail = newNode;
            length++;
        } else {
            head.prev = newNode;
            newNode.next = head;
            head = newNode;
            length++;
        }

    }

    //在链表尾部增加节点
    public void addTail(Object value) {
        Node newNode = new Node(value);
        if (length == 0) {
            head = newNode;
            tail = newNode;
            length++;
        } else {
            newNode.prev = tail;
            tail.next = newNode;
            tail = newNode;
            length++;
        }
    }

    //删除链表的头部节点
    public Node deleteHead() {
        Node temp = head;
        if (length != 0) {
            head = head.next;
            head.prev = null;
            length--;
            return temp;
        } else {
            return null;
        }
    }

    //删除链表的尾部节点
    public Node deleteTail() {
        Node temp = tail;
        if (length != 0) {
            tail = tail.prev;
            tail.next = null;
            length--;
            return temp;
        } else {
            return null;
        }
    }

    //通过值删除链表中的数据
    public Node deleteKey(Object data) {
        Node current = head;
        //遍历链表寻找该值所在的结点
        while (current != null && current.data != data) {
            current = current.next;
        }
        //若当前结点指向null则返回null,
        if (current == null) {
            return null;
        } else {
            //如果current是第一个结点
            if (current == head) {
                head = current.next;
                current.next.prev = null;
            } else if (current == tail) {
                //如果current是最后一个结点
                tail = current.prev;
                //将last指向当前结点的上一个结点(我们将当前结点除名了以后它便不再是最后一个了)
                //相应的要删除结点的上一个结点的next域应指向null
                current.prev.next = null;
            } else {
                //当前结点的上一个结点的next域应指向当前的下一个结点
                current.prev.next = current.next;
                //当前结点的下一个结点的previous域应指向当前结点的上一个结点
                current.next.prev = current.prev;
            }
        }
        return current;        //返回
    }

    //在node值插入data
    public void insertAfter(Object node, Object data) {
        Node newNode = new Node(data);
        Node current = head;
        while ((current != null) && (current.data != node)) {
            current = current.next;
        }
        //若当前结点current为空
        if (current == null) {
            //1、链表为空
            if (length == 0) {
                head = newNode;
                tail = newNode;
                length++;
                return;
            }
            //2、找不到key值
            //则在链表尾部插入一个新的结点
            newNode.prev = tail;
            tail.next = newNode;
            tail = newNode;
            length++;
            return;
        }
        //第三种情况,找到了key值
        if (current == tail) {
            newNode.prev = tail;
            tail.next = newNode;
            tail = newNode;
            length++;
        } else {
            newNode.next = current.next;
            newNode.prev = current;
            current.next.prev = newNode;
            current.next = newNode;
            length++;
        }
    }


    //查找node的节点
    public Node find(Object obj) {
        Node current = head;
        int tempsSize = length;
        while (tempsSize > 0) {
            if (current == null) {
                break;
            }
            if (obj.equals(current.data)) {
                System.out.println("查询结果" + current.data);
                return current;
            } else {
                current = current.next;
            }
            tempsSize--;
        }
        if (current == null) {
            System.out.println("查无此结果:" + obj);
        } else {
            System.out.println("查询结果:" + current.data);
        }
        return current;
    }


    public static void main(String[] args) {
        TwoWayLinkedList twoWayLinkedList = new TwoWayLinkedList();
        twoWayLinkedList.addHead("测试1");
        twoWayLinkedList.addHead("测试2");
        twoWayLinkedList.addTail("测试3");
        twoWayLinkedList.addTail("测试4");
        twoWayLinkedList.addTail("测试5");
        twoWayLinkedList.addTail("测试6");
        twoWayLinkedList.find("测试4");

        twoWayLinkedList.deleteKey("测试4");
        twoWayLinkedList.find("测试4");
        twoWayLinkedList.insertAfter("测试6", "测试7");
        twoWayLinkedList.find("测试7");
        twoWayLinkedList.deleteHead();
        twoWayLinkedList.deleteTail();
    }

}

1649313113(1).png