1. 程式人生 > 實用技巧 >JAVA筆記整理-集合框架-單鏈表-佇列結構-棧結構

JAVA筆記整理-集合框架-單鏈表-佇列結構-棧結構

一、集合框架

有關LinkedList的集合的,它是一個連結串列結構的集合

1、連結串列結構

1.1 單鏈表的結構

所謂單鏈表(Linked)在記憶體中不連續的一端記憶體空間, 連結串列的每一個元素是一個節點,每一個結點由資料元素和下一個結點的儲存位置組成,連結串列結構與陣列結構最大區別是連結結構的儲存記憶體是不連續的,而陣列結構的記憶體是連續的,連結串列結構不能與陣列結構一樣快速查詢,

​ 連結串列結構操作特點是 新增,刪除元素效率高,查詢效率低;

​ 陣列結構操作特點: 新增,刪除效率低,查詢效率高

前驅: 該節點的上一個元素的地址

後繼: 該節點的下一個元素的地址

連結串列結構中最後一個元素的”後繼“為null

1.2 單鏈表的實現

連結串列實現新增元素:

  /**
     * 新增到最後元素
     * @param obj
     */
     public void addLast(Object obj){
         //將節點新增到最後
         //add(obj , this.size);
         // 建立節點
//         Node node = new Node(obj);
//         // 找到最後一個元素的地址
//         Node lastNode = this.header;
//         for(int i = 0;i<this.size-1 ;i++){
//             lastNode  = lastNode.next;
//         }
//
//           lastNode.next=node;
         // 找最後一個結點 (由於最後一個結點的next是null)
         Node node = new Node(obj);
           Node lastNode = this.header;
           while(lastNode.next!=null){
               lastNode = lastNode.next;
           }
           lastNode.next = node;

           this.size++;

     }
單鏈練習:整體
package linked;

import javax.xml.soap.Node;

/**
 * @ClassName:JAVA
 * @Author:ZhouHongTing
 * @pate:2020/10/26 18:47
 * @Description;
 */
public class Test<T> {
    //建立連結串列頭部
     Node header; //如果有節點,那麼這就是頭節點
    int size;//計算連結串列數量

    //建立節點類
    class Node<T>{
        //節點內容
        T data;
        Node next;//下一個節點地址
        public Node(T data){
            this.data=data;
        }
        //獲取data
        public T getData(){
            return data;
        }
        //設定data
        public void setData(T data){
            this.data=data;
        }
        //獲取下一個節點地址
        public Node next(){
            return next;
        }
        //設定下一個節點地址
        public void setNext(){
            this.next=next;
        }
    }
    /**
     * 將元素新增到第一個節點
      */
    public void addFirst(T n){
        //建立節點
        Node node=new Node(n);
        node.next=this.header;//新節點的後繼就是原節點頭部
        this.header=node;//將頭節點變為新要新增的節點
        //節點計數器加一
        size++;
    }
    /**
     * 新增到最後元素
     */
    public void addLast(T n){
        //建立新節點
        Node node=new Node(n);
       Node lastNode=this.header;//建立一個最後節點,賦予頭值從頭開始算,求出最後節點
       while (lastNode.next!=null){
           lastNode=lastNode.next;
       }
       lastNode.next=node;
       this.size++;
    }
    /**
     * 插入一個指定下標節點
     */
    public void addIndex(T n,int index){
     Node node=new Node(n);//建立新節點

     Node cle=this.header;//建立 一個前節點獲取頭節點值作為初始值
        Node cur;//建立一個後一個節點,裝前一個節點的(下一個節點地址)
        for(int i=0;i<index-1;i++){
            cle=cle.next;//迴圈判斷到指定下標的前一個節點
        }
        cur=cle.next;//將前一個節點的下個節點地址存入
        cle.next=node;//前一個節點的下一個節點地址就是當前插入元素節點
        node.next=cur;//當前節點的下個節點位置就是原先前節點的下個節點地址
        this.size++;
    }
    /**
     * 刪除第一個節點
     */
    public void removeFirst(){
        //先判斷是否存在節點
        if(this.size==0){
            throw new IllegalArgumentException("沒有需要刪除的節點");
        }
        //獲取當前節點的"後繼"
        Node node=this.header.next;//獲取當前頭節點的後繼節點
        //讓後繼節點替換頭節點便完成刪除頭節點
        this.header=node;
        this.size--;
    }
    /**
     * 刪除最後節點
     */
    public void removeLast(){
        //判斷是否存在節點
        if(this.size==0){
            throw new IllegalArgumentException("沒有節點");
        }
        //找到最後一個節點的前一個節點,並將它下個節點地址改為null
        Node cur=this.header;
        Node pre=header;
        while (cur.next!=null){
            pre=cur; //獲取的後繼節點就是下一個節點
            cur=cur.next;//獲取節點後繼,直到cur.next=null
        }
        pre.next=null;
        this.size--;

    }

    /**
     * 根據下標獲取節點
     * @param
     */
    public Node getShowInfo(int index){
        //判斷是否為空節點
        if(this.size==0){
            throw new IllegalArgumentException("這是空節點");
        }
        if(index==0){
            return this.header;
        }
        //查詢指定下標的元素
        Node cur=this.header;//從第一個元素開始
        int j=0;
        while (index!=j&&index<this.size){
            cur=cur.next;
            j++;
        }
        return cur;
    }
    //測試
    public static void main(String[]args){
        Test test=new Test();
        test.addFirst("hello1");
        test.addFirst("hello2");
        test.addFirst("hello3");
        for(int i=0;i<test.size;i++){
            System.out.println(test.getShowInfo(i).getData());//輸出新增的節點元素
        }
        test.addIndex("hello",1);//在指定位置新增節點元素
        System.out.println(test.size);  //檢視節點數量
        test.removeFirst();   //刪除第一個節點元素
        System.out.println(test.header.getData());
        test.removeLast(); //刪除最後一個節點元素
        System.out.println(test.getShowInfo(test.size-1).getData());



    }


}

  /**
     * 刪除第一個節點
     * @param index
     * @return
     */
    public void removeFirst(){
        //刪除第一個節點
        if(this.size==0){
            throw new IllegalArgumentException("沒有需要刪除的原始");
        }
        //  獲取當前連線的“後繼”
        Node node =  this.header.next;
        // 並讓後繼作為頭
        this.header = node;
        this.size--;
    }

    /**
     * 刪除最後節點
     */
    public void removeLast(){
        //刪除是否存在資料
        if(this.size==0){
            throw new IllegalArgumentException("沒有需要刪除的原始");
        }
        // 找最後一個元素的前一個 地址   ,並將該地址的next 改為null
        Node cur  = this.header;
        Node pre = this.header;
        while(cur.next!=null){
               pre = cur;
                // 下一個變為當前
               cur =  cur.next;
        }
         // 最後一個元素  就是 當前
        pre.next = null;
        size--;
    }

2、佇列結構

佇列結構(Queue): 在基於連結串列結構的基礎上 ,實現的一種“先進先出”的結構, 常用操作 入隊(put),出隊(pop) ,設定佇列的頭結點 和 尾結點

package com.j2008.dataStruct;

public class MyQueue<T> {
    // 頭結點
    private Node front;
    //  尾結點
    private Node tail;
    // 大小
    private int size;

    public MyQueue(){
        //  頭,尾為空
        this.front= this.tail=null;
    }

    class Node{
        private T obj;
        private Node next;
        public Node(T obj){
            this.obj = obj;
        }

        public T getObj() {
            return obj;
        }

        public void setObj(T obj) {
            this.obj = obj;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }

    /**
     * 入隊 : 將元素新增到佇列的尾部
     */
    public void put(T obj){
        // 建立節點
        Node node = new Node(obj);
        // 如果元素為空 則頭就尾,尾就是頭
        if(isEmpty()){
            this.front = this.tail = node;
            return ;
        }
        // 將新元素的地址 作為尾的next
        this.tail.next=node;
        //將新元素的結點 作為尾節點
        this.tail = node;

        this.size++;
    }

    /**
     * 出隊: 將元素從佇列的頭部移除 (保持與佇列脫離關係)
     * @return
     */
    public T pop(){
        if(isEmpty()){
            throw new IllegalArgumentException("沒有彈出的原始");
        }
        // 移除頭部元素
        Node popNode = this.front;
        // 設定現在的頭元素是下一個
        this.front = popNode.next;
        //  將彈出的元素next 設定null,與佇列脫離關係
        popNode.next=null;
        this.size--;
        // 如果沒有元素了 則需要 設定頭尾都是null
        if(this.size<0){
            this.front=this.tail=null;
        }
        return  popNode.getObj();
    }

    /**
     * 判斷元素是否為空
     * @return
     */
    public boolean isEmpty(){
        if(this.front==null && this.tail==null){
            return true;
        }
        return false;
    }

}

3、棧結構

棧(Stack)結構也是常用資料結構之一,它具有 “後進先出” 的特點

public class MyStack<T> {
    // 定義一個數組 ,用於儲存元素
    private Object[] obj;
    private int size;
    public MyStack(){
        obj = new Object[10];
        size=0;
    }

    /**
     * 入棧: 壓入棧頂元素
     * @param t
     */
    public void push(T t){
        expandCapacity(size+1);
        obj[size]=t;
        size++;
    }

    /**
     *  返回棧頂元素:peek
     */
    public T peek(){

        if(size>0) {
            return (T) obj[size - 1];
        }
        return  null;
    }

    /**
     * 出棧: 返回棧頂的元素,並刪除該元素
     * @return
     */
    public T pop(){
        T t = peek();
        if(size>0) {
            // 將最後一個元素 刪除
            obj[size - 1] = null;
            size--;
        }
        return t;
    }

    /**
     * 是否為空元素
     * @return
     */
    public boolean  isEmpty(){
        return  size==0;
    }
    /**
     * 擴容陣列大小 : 擴容1.5倍
     */
    public void expandCapacity(int size){
        if(obj.length< size){
            // 需要擴容
            int length = size*3/2 + 1;
           this.obj =  Arrays.copyOf(this.obj,length);
        }
    }

}