用JAVA数组自己实现链表(单链表,双向链表)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qichangjian/article/details/86661240

我们知道,数组作为数据存储结构有一定的缺陷。在无序数组中,搜索时低效的;而在有序数组中,插入效率又很低;不管在哪一种数组中删除效率都很低。况且一个数组创建后,它的大小是无法改变的。

而链表可能是继数组之后第二种使用得最广泛的通用数据结构了。
这里主要来讨论并写一个单链表和双向链表。

顾名思义,单链表只能从表头到表尾的顺序,每个节点中保存了指向下一个节点的指针;
双向链表则可以反向遍历,因为节点中既保存了向后节点的指针,又保存了向前节点的指针。

由于链表结构相对简单,这里不再赘述,直接通过程序来查看它们常见的操作:

单链表实现

/**
* 单向链表
* 定义链表上的节点
*/
public class Link {
   public int data;//节点的内容
   public Link next;//下一个节点

   //初始化
   public Link(int data) {
       this.data = data;
       this.next = null;
   }

   //打印节点内容
   public void displayLink(){
       System.out.println("{" + data + "}");
   }
}

/**
 * 单向链表
 */
public class LinkedList {
    private Link first;//第一个节点
    private int nElem;//链表中节点数量

    public LinkedList(){
        first = null;
        nElem = 0;
    }


    //添加头结点
    public void insertFirst(int value){
        Link newLink = new Link(value);
        newLink.next = first;//newLink-->old first
        first = newLink;//first-->newLink
        nElem ++;
    }

    //删除头节点
    public Link deleteFirst(){
        if(isEmpty()){
            System.out.println("链表为空");
            return null;
        }
        Link temp = first;
        first = first.next;
        nElem --;
        return temp;
    }

    /************************************************************
     ***下面是有序链表的插入***
     ***这样简单排序就可以用链表来实现,复杂度为O(N)
     ***定义一个方法,传入一个数组,
     ***在方法内,遍历数组并调用insert方法就可以将数组中的数据排好序
     ***********************************************************/
    public void insert(int value){
        Link newLink = new Link(value);//要插入的Link节点
        Link previous = null;//前一个link节点
        Link current = first;//因为是有序链表,从第一个开始
        while(current != null && value > current.data){//当前link不是空,插入的数据大于当前link值
            previous = current;//记录当前为前一个link节点
            current = current.next;//当前link向下找
        }
        if(previous == null){//前一个为null证明只有没有插入link节点,直接插入就行
            first = newLink;
        }else {
            previous.next = newLink;//插入这个link在小于value的link下,后边link为当前节点
        }
        newLink.next = current;//当前节点
        nElem ++;//有序链表长度+1
    }

    //查找特定的节点
    public Link find(int value){
        Link current = first;//从第一个开始查找
        while(current.data != value){
            if(current.next == null){//下一个为空
                return null;
            }else{
                current = current.next;//查找下一个节点
            }
        }
        return current;
    }

    //删除特定的节点
    public Link delete(int value){
        Link current = first;
        Link previous = first;//记录上一个Link,因为要删除节点,节点的指向要发生变化
        while(current.data != value){
            if(current.next == null){
                return null;
            }
            previous = current;
            current = current.next;
        }
        if(current == first){//如要要删除的是第一个
            first = first.next;
        }else{
            previous.next = current.next;//删除link的上一个指向为当前link的下一个link
        }
        nElem --;
        return current;
    }

    //查看链表中的数据
    public void displayList(){
        if(isEmpty()){//为空直接返回
            System.out.println("链表为空!");
            return;
        }
        Link current = first;
        while(current != null){
            current.displayLink();//调用link中的方法,打印当前link的值
            current = current.next;
        }
        System.out.println(" ");
    }

    //链表是否为空
    public boolean isEmpty(){
        return (first == null);
    }

    //链表中节点个数
    public int size(){
        return nElem;
    }
}

/*
    测试有序单向链表
 */
public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
        linkedList.insert(1);
        linkedList.insertFirst(2);
        linkedList.insert(3);
        linkedList.displayList();
        System.out.println(linkedList.isEmpty());
        System.out.println(linkedList.size());
        linkedList.find(1).displayLink();
        linkedList.deleteFirst();
        linkedList.delete(3);
        linkedList.displayList();
    }
}

双向链表

/**
 * 双向链表中的node
 */
public class Node {
    public long data;//当前node的数据值
    public Node next;//后一个node
    public Node previous;//前一个node

    public Node(long value) {
        this.data = value;
        this.next = null;
        this.previous = null;
    }

    //打印节点中node值
    public void displayLink(){
        System.out.print(data + " ");
    }
}

/**
 * 双向链表的具体实现
 */
public class DoubleLinkedList {
    private Node first;//头节点
    private Node last;//尾节点
    private int size;//链表长度

    public DoubleLinkedList() {
        this.first = null;
        this.last = null;
        this.size = 0;
    }

    //链表大小
    public int size(){
        return size;
    }

    //链表是否为空
    public boolean isEmpty(){
        return (first == null);
    }

    //插入头节点
    public void insertFirst(long value){
        Node newLink = new Node(value);
        if(isEmpty()){
            last = newLink;
        }else {
            //前first的node赋值为newLink
            first.previous = newLink;//newLink <-- oldFirst.previous
            //newLink的下一个node为first
            newLink.next = first;//newLink.next --> first
        }
        first = newLink;//first --> newLink//第一个赋值为新插入的
        size ++;
    }

    //插入尾节点
    public void insertLast(long value){
        Node newLink = new Node(value);
        if(isEmpty()){
            first = newLink;
        }else{
            last.next = newLink;
            newLink.previous = last;
        }
        last = newLink;//最后一个赋值为新插入的
        size ++;
    }

    //删除头节点
    public Node deleteFirst(){
        if(first == null){
            System.out.println("链表为空");
            return null;
        }
        Node temp = first;
        if(first.next == null){//如果只有一个节点
            last = null;
        }else{
            first.next.previous = null;//就是first的下一个node的前指针为空
        }
        first = first.next;//第一个为第一个的下一个
        size --;
        return temp;
    }

    //删除尾节点
    public Node deleteLast(){
        if(last == null){//最后一个节点为空,证明没有
            System.out.println("链表为空");
            return null;
        }
        Node temp = last;//暂存要删除的最后一个
        if(last.previous == null){//只有一个节点
            first = null;
        }else{
            last.previous.next = null;//last的前一个的next为null
        }
        last = last.previous;
        size --;
        return temp;
    }

    //在key后面插入值为value的新节点
    public boolean insertAfter(long key,long value){
        Node current = first;//从第一个开始
        while(current.data != key){//对比传入的date
            current = current.next;//下一个
            if(current == null){//如果下一个为空,就是最后一个
                System.out.println("不存在值为" + value + "的节点!");
                return false;
            }
        }
        if(current == last){//当前值为最后一个
            insertLast(value);
        }else{
            Node newLink = new Node(value);//要插入的节点
            newLink.next = current.next;//插入节点的下一个为匹配节点的下一个
            current.next.previous = newLink;//匹配节点的前一个为新加入的节点
            newLink.previous = current;//插入的前一个为匹配节点
            current.next = newLink;//匹配节点的后一个节点为新加入的节点
            size ++;
        }
        return true;//插入成功
    }

    //删除指定位置的节点
    public Node deleteNode(long key){
        Node current = first;//当前节点为第一个节点
        while(current.data != key){
            current = current.next;
            if(current == null){
                System.out.println("不存在该节点");
                return null;
            }
        }
        if(current == first){//如果匹配的是第一个
            deleteFirst();
        }else if(current == last){
            deleteLast();//匹配的是最后一个
        }else{
            current.previous.next = current.next;//当前节点的前一个的后一个为 当前的后一个
            current.next.previous = current.previous;//当前节点的后一个的前一个为 当前的前一个
            size --;
        }
        return current;
    }

    //从头到尾遍历链表
    public void displayForward(){
        System.out.println("List(first --> last):");
        System.out.print("[");
        Node current = first;
        while(current != null){
            current.displayLink();//调用节点的显示方法
            current = current.next;
        }
        System.out.println("]");
    }

    //从尾到头遍历链表
    public void displayBackward(){
        System.out.println("List(last --> first)");
        System.out.print("[");
        Node current = last;
        while(current != null){
            current.displayLink();
            current = current.previous;
        }
        System.out.println("]");
    }

}

/**
 * 双向链表测试
 */
public class DoubleLinkedListDemo {
    public static void main(String[] args) {
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        doubleLinkedList.insertLast(9);
        doubleLinkedList.insertFirst(1);
        doubleLinkedList.insertAfter(1,2);
        doubleLinkedList.insertAfter(2,3);
        doubleLinkedList.insertAfter(9,10);
        doubleLinkedList.displayBackward();
        doubleLinkedList.displayForward();
        System.out.println(doubleLinkedList.isEmpty());
        System.out.println(doubleLinkedList.size());

        //删除测试
        doubleLinkedList.deleteFirst();
        doubleLinkedList.deleteLast();
        doubleLinkedList.deleteNode(3);
        doubleLinkedList.displayBackward();
        doubleLinkedList.displayForward();
    }
}

其他:
用JAVA数组自己实现一个栈
用JAVA数组自己实现一个队列(普通队列以及优先级队列)
java中一些反射,collection,多线程,排序,红黑数,链表等总结整理

猜你喜欢

转载自blog.csdn.net/qichangjian/article/details/86661240
今日推荐