Java 八大数据结构之链表

一:定义
数据结构:是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
image.png
二:链表(Linked List)
链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接("links")
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
1.单向链表(Single-Linked List)
单链表是链表中结构最简单的,一个单链表的节点(Node)分为两部分,第一部分(data)保存或者显示关于节点的信息,另一部分存储下一个节点的地址。最后一个节点存储地址的部分指向空值
单向链表只可向一个方向遍历,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。
image.png
image.png
单向链表的增删改查的实现

public class SingleLinkedList {
    private int size;//链表节点的个数
    private Node head;//头节点

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

    //定义一个节点内部类,包含数据Object,和Node节点指针
    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 (size == 0) {
            head = newHead;
        } else {
            newHead.next = head;
            head = newHead;
        }
        size++;
        return obj;
    }

    //在链表头删除元素
    public Object deleteHead() {
        Object obj = head.data;
        head = head.next;
        size--;
        return obj;
    }

    //查找指定元素,找到了返回null
    public Node find(Object obj) {
        Node current = head;
        int tempSize = size;
        while (tempSize > 0) {
            if (obj.equals(current.data)) {
                return current;
            } else {
                current = current.next;
            }
            tempSize--;
        }
        return null;
    }

    //删除指定的元素,删除成功返回true
    public boolean delete(Object value) {
        if (size == 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;
            size--;
        } else {//删除的节点不是第一个节点
            previous.next = current.next;
            size--;
        }
        return true;
    }

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


    //显示节点信息
    public void display() {
        if (size > 0) {
            Node node = head;
            int tempSize = size;
            if (tempSize == 1) {//当前链表只有一个节点
                System.out.println("[" + node.data + "]");
                return;
            }
            while (tempSize > 0) {
                if (node.equals(head)) {
                    System.out.print("[" + node.data + "->");
                } else if (node.next == null) {
                    System.out.print(node.data + "]");
                } else {
                    System.out.print(node.data + "->");
                }
                node = node.next;
                tempSize--;
            }
            System.out.println();
        } else {//如果链表一个节点都没有,直接打印[]
            System.out.println("[]");
        }

    }
}

调用

  SingleLinkedList singleLinkedList=new SingleLinkedList();
                singleLinkedList.addHead("Rocky");
                singleLinkedList.addHead("Tom");
                singleLinkedList.addHead("Jacky");
                singleLinkedList.addHead("Mark");
                //打印当前链表信息
                singleLinkedList.display();
                //删除Tom
                singleLinkedList.delete("Tom");
                singleLinkedList.display();
                //查找Rocky
                System.out.println( singleLinkedList.find("Rocky"));
                
                
  //结果
System.out: [Mark->Jacky->Tom->Rocky]
System.out: [Mark->Jacky->Rocky]
System.out: com.ruan.mygitignore.SingleLinkedList$Node@c115983
             

2.双端链表(它也是单向的只是增加了一个尾结点,这个可以向尾部添加数据,和双向链表区别)
对于单项链表,我们如果想在尾部添加一个节点,那么必须从头部一直遍历到尾部,找到尾节点,然后在尾节点后面插入一个节点。这样操作很麻烦,如果我们在设计链表的时候多个对尾节点的引用,那么会简单很多。
image.png

public class DoublePointLinkedList {
     private Node head;//头节点
    private Node tail;//尾节点
     private int size;//节点的个数
      
       private class Node{
           private Object data;
          private Node next;
         
         public Node(Object data){
              this.data = data;
         }
    }
      
     public DoublePointLinkedList(){
          size = 0;
          head = null;
          tail = null;
     }
      
      //链表头新增节点
     public void addHead(Object data){
         Node node = new Node(data);
          if(size == 0){//如果链表为空,那么头节点和尾节点都是该新增节点
             head = node;
              tail = node;
              size++;
         }else{
              node.next = head;
             head = node;
              size++;
          }
     }
     
      //链表尾新增节点
      public void addTail(Object data){
          Node node = new Node(data);
          if(size == 0){//如果链表为空,那么头节点和尾节点都是该新增节点
             head = node;
              tail = node;
             size++;
         }else{
              tail.next = node;
            tail = node;
              size++;
         }
      }
      
      //删除头部节点,成功返回true,失败返回false
    public boolean deleteHead(){
         if(size == 0){//当前链表节点数为0
             return false;
         }
          if(head.next == null){//当前链表节点数为1
              head = null;
             tail = null;
          }else{
             head = head.next;
          }
          size--;
          return true;
      }
      //判断是否为空
      public boolean isEmpty(){
          return (size ==0);
      }
      //获得链表的节点个数
      public int getSize(){
          return size;
      }
      
      //显示节点信息
      public void display(){
         if(size >0){
              Node node = head;
              int tempSize = size;
             if(tempSize == 1){//当前链表只有一个节点
                  System.out.println("["+node.data+"]");
                  return;
              }
              while(tempSize>0){
                  if(node.equals(head)){
                      System.out.print("["+node.data+"->");
                 }else if(node.next == null){
                     System.out.print(node.data+"]");
                  }else{
                     System.out.print(node.data+"->");
                 }
                  node = node.next;
                 tempSize--;
             }
              System.out.println();
          }else{//如果链表一个节点都没有,直接打印[]
             System.out.println("[]");
          }
    }
  
 }

3.双向链表
我们知道单向链表只能从一个方向遍历,那么双向链表它可以从两个方向遍历。
image.png
双向链表实现

public class TwoWayLinkedList {

    private Node head;//表示链表头
    private Node tail;//表示链表尾
    private int size;//表示链表的节点个数


    //内部类构建了数据,前驱指针prev,向前寻找,后驱指针next 向后查找

    private class Node {
        private Object data;
        private Node next;//链接后一个节点
        private Node prev;//链接前一个节点

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

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

    //在链表头增加节点
    public void addHead(Object value) {
        Node newNode = new Node(value);
        if (size == 0) {
            head = newNode;
            tail = newNode;
            size++;
        } else {
            head.prev = newNode;//原节点的前驱指针链接新节点
            newNode.next = head;//新节点的后驱指针链接原节点
            head = newNode;
            size++;
        }

    }

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

    }

    //删除链表头
    public Node deleteHead() {
        Node temp = head;
        if (size != 0) {
            head = head.next;
            head.prev = null;
            size--;
        }
        return temp;
    }

    //删除链表尾
    public Node deleteTail() {
        Node temp = tail;
        if (size != 0) {
            tail = tail.prev;
            tail.next = null;
            size--;
        }
        return temp;
    }

    //获得链表的节点个数
    public int getSize() {
        return size;
    }

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


    //显示节点信息
    public void display() {
        if (size > 0) {
            Node node = head;
            int tempSize = size;
            if (tempSize == 1) {//当前链表只有一个节点
                System.out.println("[" + node.data + "]");
                return;
            }
            while (tempSize > 0) {
                if (node.equals(head)) {
                    System.out.print("[" + node.data + "->");
                } else if (node.next == null) {
                    System.out.print(node.data + "]");
                } else {
                    System.out.print(node.data + "->");
                }
                node = node.next;
                tempSize--;
            }
            System.out.println();
        } else {//如果链表一个节点都没有,直接打印[]
            System.out.println("[]");
        }

    }
}

调用

TwoWayLinkedList twoWayLinkedList=new TwoWayLinkedList();
                twoWayLinkedList.addHead("Rocky");
                twoWayLinkedList.addHead("Mark");
                twoWayLinkedList.addTail("Jack");
                twoWayLinkedList.addTail("Sam");
                twoWayLinkedList.display();

image.png

END:弱小和无知,不是生存的障碍,傲慢才是。


Rocky_ruan
57 声望5 粉丝

不积跬步,无以至千里