java實現單連結串列、棧、佇列三種資料結構

學海無涯——遠航發表於2020-10-27

一、單連結串列

1、在我們資料結構中,單連結串列非常重要。它裡面的資料元素是以結點為單位,每個結點是由資料元素的資料和下一個結點的地址組成,在java集合框架裡面
LinkedList、HashMap(陣列加連結串列)等等的底層都是用連結串列實現的。
2、下面是單連結串列的幾個特點:
資料元素在記憶體中存放的地址是不連續的:單連結串列的結點裡面還定義一個結點,它裡面儲存著下一個結點的記憶體地址,在例項化物件的時候,jvm會開闢不同記憶體空間,並且是不連續的。
新增效率高:新增一個元素時,先找到插入位置的前一個,只需要將1,2個元素的連線斷開,將插入結點的next指向第一個元素的next(1),然後將第一個元素的next指向插入結點(2),
不用在挪動後面元素。

刪除效率高:刪除一個元素時,先找到刪除位置,將前一個的next指向刪除位置的next,不用在挪動後面元素。

查詢效率低:查詢的時候必須從頭開始,依次遍歷,而陣列因為它的記憶體是連續的,可以直接通過索引查詢。
3、下面通過程式碼來實現單連結串列結構:

  package com.tlinkedList;

/**
* User:zhang
* Date:2020/10/26
**/
public class TLinkedList<T> {
  private Node head;//連結串列頭部
  private int size;//連結串列元素的個數
  public TLinkedList(){
      head=null;
      size=0;
  }
//    將結點作為內部類。也可以新建一個Node類,作為結點
  class Node{
      private Node next;//下一個結點
      private T t;//結點的資料
      public Node(T t){
          this.t=t;
      }

      public T getT() {
          return t;
      }

      public void setT(T t) {
          this.t = t;
      }
  }
//    在連結串列頭部新增一個結點
  public void addFirst(T t){
      Node node = new Node(t);
      node.next=head;
      head=node;
      size++;
  }
//    在連結串列中間新增一個結點
  public void addMid(T t,int index){
      Node node = new Node(t);
      Node mid=head;
      for (int i = 0; i < index - 1; i++) {
          mid=mid.next;
      }
      node.next=mid.next;
      mid.next=node;
      size++;
  }
//    在連結串列尾部新增一個結點
  public void addLast(T t){
      Node node = new Node(t);
      Node last=head;
      while (last.next!=null){
          last=last.next;
      }
      last.next=node;
      node.next=null;
      size++;
  }
//    刪除連結串列的頭結點
  public void removeFirst(){
      head=head.next;
      size--;
  }
//    刪除連結串列的中間元素
  public void removeMid(int index){
      Node mid=head;
      if (index==0){
          removeFirst();
          return;
      }
      int j=0;
      Node qMid=head;
      while (j<index){
          qMid=mid;
          mid=mid.next;
          j++;
      }
      qMid.next=mid.next;
      size--;
  }
//    刪除連結串列的尾結點
  public void removeLast(){
      Node mid=head;
      Node qMid=head;
      while (mid.next!=null){
           qMid=mid;
           mid=mid.next;
      }
      qMid.next= null;
      size--;
  }
//    獲取連結串列指定下標的結點
  public Node get(int index){
      Node mid=head;
      if (index==0){
          return head;
      }
      int j=0;
      while (j<index){
          mid=mid.next;
          j++;
      }
      return mid;
  }
  public static void main(String[] args) {
      TLinkedList<String> linkedList = new TLinkedList<>();
      linkedList.addFirst("hello1");
      linkedList.addFirst("hello2");
      linkedList.addFirst("hello3");
      for (int i = 0; i < linkedList.size; i++) {
          System.out.println(linkedList.get(i).getT());
      }
//        linkedList.removeLast();
//        linkedList.removeFirst();
//        linkedList.addLast("hello4");
      linkedList.addMid("hello",2);
      System.out.println("--------------");
      for (int i = 0; i < linkedList.size; i++) {
          System.out.println(linkedList.get(i).getT());
      }
  }
}

結果如下:

二、棧(Stack)

1、一提到棧我們腦海就會浮現四個字“先進後出”,沒錯,它就是棧的最大特點。

2、棧的應用場景也非常多,比如將字串反轉、jvm裡面的棧區等等。
3、棧裡面的主要操作有:
push(入棧):將一個資料元素從尾部插入
pop(出棧):將一個資料元素從尾部刪除
peek(返回棧頂元素):將棧頂元素的資料返回
相當於只有一個開口就是尾部,只能從尾進,從尾出。
4、下面通過連結串列結構實現棧結構:

package com.tStack;


/**
* User:zhang
* Date:2020/10/26
**/
public class Test_Stack<T> {
  private Node head;//棧的頭結點
  private int size;//棧的元素個數
  class Node{
      private Node next;//下一個結點
      private T t;//結點的資料
      public Node(T t){
          this.t=t;
      }

      public T getT() {
          return t;
      }

      public void setT(T t) {
          this.t = t;
      }
  }

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

  public static void main(String[] args) {
      Test_Stack<String> TStack = new Test_Stack<>();
      TStack.push("hello1");
      TStack.push("hello2");
      TStack.push("hello3");
      for (int i = 0; i < 3; i++) {
          System.out.println(TStack.pop());
      }
  }
//    入棧
  public void push(T t){
      Node node = new Node(t);
      if (size==0){
          node.next=head;
          head=node;
          size++;
          return;
      }
      if (size==1){
          head.next=node;
          node.next=null;
          size++;
          return;
      }
      Node lastNode=head;
      while (lastNode.next!=null){
           lastNode=lastNode.next;
      }
      lastNode.next=node;
      node.next=null;
      size++;
  }
//    出棧
  public T pop(){
      if (size==0){
          System.out.println("棧內無值");
          return null;
      }
      if (size==1){
          T t = head.getT();
          head=null;
          size--;
          return t;
      }
      Node lastNode=head;
      Node qNode=head;
      while (lastNode.next!=null){
          qNode=lastNode;
          lastNode=lastNode.next;
      }
      T t = lastNode.getT();
      qNode.next=null;
      size--;
      return t;
  }
//    獲取棧裡面元素的個數
  public int getSize(){
      return size;
  }
//    返回棧頂元素
  public T peek(){
      if (size==0){
          System.out.println("棧內無值");
          return null;
      }
      if (size==1){
          return head.getT();
      }
      Node lastNode=head;
      while (lastNode.next!=null){
          lastNode=lastNode.next;
      }
      return lastNode.getT();
  }
}

結果:

三、佇列(Queue)

1、佇列的特點也用“先進先出”四個字來概括。就是先進去的元素先輸出出來。
2、我們常見的訊息佇列就是佇列結構實現的。
3、佇列的常見操作如下:
put(入隊):將一個結點插入到尾部。
pop(出隊): 將頭結點的下一個結點作為頭,然後將原來的頭結點刪除。
4、通過連結串列結構實現佇列:

package com.tQueue;

/**
 * User:zhang
 * Date:2020/10/26
 **/
public class TQueue<T> {
    private Node front;//頭結點
    private Node tail;//尾結點
    private int size;//佇列中元素的個數
    class Node {
        private Node next;//下一個結點
        private T t;//結點的資料

        public Node(T t) {
            this.t = t;
        }

        public T getT() {
            return t;
        }

        public void setT(T t) {
            this.t = t;
        }
    }
    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public TQueue() {
        front = tail = null;
    }

    //    入隊
    public void put(T t) {
        Node node = new Node(t);
        if (size == 0) {
            front = tail = node;
            size++;
            return;
        }
        Node lastNode = front;
        while (lastNode.next != null) {
            lastNode = lastNode.next;
        }
        lastNode.next = node;
        tail = node;
        size++;
    }

    //    出隊
    public T pop() {
        if (size == 0) {
            System.out.println("佇列中無值");
            return null;
        }
        T t = front.getT();
        front=front.next;
        size--;
        return t;
    }

    public static void main(String[] args) {
        TQueue<String> tQueue = new TQueue<>();
        tQueue.put("Hello1");
        tQueue.put("Hello2");
        tQueue.put("Hello3");
        for (int i = 0; i < 3; i++) {
            System.out.println(tQueue.pop());
        }
    }
}

結果:

文章有不足之處,歡迎大家留言指正,謝謝大家啦!

相關文章