Java資料結構之線性表(2)

來源:互聯網
上載者:User

標籤:

從這裡開始將要進行Java資料結構的相關講解,Are you ready?Let‘s go~~

java中的資料結構模型可以分為一下幾部分:

1.線性結構

2.樹形結構

3.圖形或者網狀結構

接下來的幾張,我們將會分別講解這幾種資料結構,主要也是通過Java代碼的方式來講解相應的資料結構。

今天要講解的是:Java線性結構

Java資料結構之線性結構

說到線性結構的話,我們可以根據其實現方式分為兩類:

1)順序結構的線性表

2)鏈式結構的線性表

3)棧和隊列的線性表

對於1)和2)的講解,請參考下面的地址:

下面主要講解線性結構中的棧和隊列。

  1.線性結構之棧的講解

    所謂棧是一種特殊的線性結構,它的特點在於只允許我們線上性表的尾端進行insert和remove操作。可以理解為是一種受限的

    線性表。往線性表中加入一個元素我們稱為入棧,從線性表中移除一個元素我們稱為出棧。實在不懂,百度一下你就知道了。

    在Java的jdk中的實現以Stack(底層繼承的是Vector類)和LinkedList(裡面同樣實現了push,pop,peek等操作)為主,還是那句話,感興趣的

    自己查看原始碼即可。

    下面我們進行相關模仿,

    首先通過數組來模仿入棧和出棧操作:

    

package com.yonyou.test;import java.util.Arrays;/** * 測試類別 * @author 小浩 * @建立日期 2015-3-20 */public class Test { public static void main(String[] args) {   SequenceStack<String> stack=new SequenceStack<String>();System.out.println("順序棧的初始化長度為:"+stack.length());stack.push("Hello");stack.push("World");stack.push("天下太平");System.out.println("當前stack中的元素為:"+stack);System.out.println("當前stack.peek();中的元素為:"+stack.peek());System.out.println("當前元素線性表是否為空白:"+stack.empty());} }/** * 建立一個線性棧 * 注意這個類是線程不安全的,在多線程下不要使用 * @author 小浩 * @建立日期 2015-3-20 * @param <T> */class SequenceStack<T>{//線性棧的預設長度為10private int DEFAULT_SIZE = 10;// 儲存數組的長度。private int capacity;// 定義當底層數組容量不夠時,程式每次增加的數組長度private int capacityIncrement = 0;// 定義一個數組用於儲存順序棧的元素private Object[] elementData;// 儲存順序棧中元素的當前個數private int size = 0;    /**     * 以預設數組長度建立空順序棧     */public SequenceStack(){capacity = DEFAULT_SIZE;elementData = new Object[capacity];}   /**    * 以一個初始化元素來建立順序棧    * @param element    */public SequenceStack(T element){this();elementData[0] = element;size++;}/** * 以指定長度的數組來建立順序棧 * @param element 指定順序棧中第一個元素 * @param initSize 指定順序棧底層數組的長度 */public SequenceStack(T element , int initSize){this.capacity = initSize;elementData = new Object[capacity];elementData[0] = element;size++;}/** * 以指定長度的數組來建立順序棧 * @param element 指定順序棧中第一個元素 * @param initSize 指定順序棧底層數組的長度 * @param capacityIncrement 指定當順序棧的底層數組的長度不夠時,底層數組每次增加的長度 */public SequenceStack(T element , int initSize, int capacityIncrement){this.capacity = initSize;this.capacityIncrement = capacityIncrement;elementData = new Object[capacity];elementData[0] = element;size++;}/** * 擷取順序棧的大小 * @return */public int length(){return size;}/** * 入棧 * @param element */public void push(T element){ensureCapacity(size + 1);elementData[size++] = element;}/** * 很麻煩,而且效能很差 * @param minCapacity */private void ensureCapacity(int minCapacity){// 如果數組的原有長度小於目前所需的長度if (minCapacity > capacity){if (capacityIncrement > 0){while (capacity < minCapacity){// 不斷地將capacity長度加capacityIncrement,// 直到capacity大於minCapacity為止capacity += capacityIncrement;}}else{// 不斷地將capacity * 2,直到capacity大於minCapacity為止while (capacity < minCapacity){capacity <<= 1;}}elementData = Arrays.copyOf(elementData , capacity);}}/** * 出棧 * @return */@SuppressWarnings("unchecked")public T pop(){T oldValue = (T)elementData[size - 1];// 釋放棧頂元素elementData[--size] = null;return oldValue;}/** * 返回棧頂元素,但不刪除棧頂元素 * @return */@SuppressWarnings("unchecked")public T peek(){return (T)elementData[size - 1];}/** * 判斷順序棧是否為空白棧 * @return */public boolean empty(){return size == 0;}     /**      * 清空順序棧      */public void clear(){// 將底層數組所有元素賦為nullArrays.fill(elementData , null);size = 0;}/** * 重寫toString */public String toString(){if (size == 0){return "[]";}else{StringBuilder sb = new StringBuilder("[");for (int i = size - 1  ; i > -1 ; i-- ){sb.append(elementData[i].toString() + ", ");}int len = sb.length();return sb.delete(len - 2 , len).append("]").toString();}}}

 

   其次通過鏈式儲存來模仿入棧和出棧操作,具體內容可以看下面的代碼:

  

package com.yonyou.test;/** * 測試類別 * @author 小浩 * @建立日期 2015-3-20 */public class Test { public static void main(String[] args) {LinkStack<String> stack=new LinkStack<String>();System.out.println("順序棧的初始化長度為:"+stack.length());stack.push("Hello");stack.push("World");stack.push("天下太平");System.out.println("當前stack中的元素為:"+stack);System.out.println("當前stack.peek();中的元素為:"+stack.peek());System.out.println("當前元素線性表是否為空白:"+stack.empty());} }/** * 建立一個鏈式儲存的線性棧 * 注意這個類是線程不安全的,在多線程下不要使用 * @author 小浩 * @建立日期 2015-3-20 * @param <T> */class  LinkStack<T>{// 定義一個內部類Node,Node執行個體代錶鏈棧的節點。private class Node{// 儲存節點的資料private T data;// 指向下個節點的引用private Node next;// 無參數的構造器public Node(){}// 初始化全部屬性的構造器public Node(T data , Node next){this.data = data;this.next = next;}}// 儲存該鏈棧的棧頂元素private Node top;// 儲存該鏈棧中已包含的節點數private int size;/** * 建立空鏈棧 */public LinkStack(){// 空鏈棧,top的值為nulltop = null;}/** * 以指定資料元素來建立鏈棧,該鏈棧只有一個元素 * @param element */public LinkStack(T element){top = new Node(element , null);size++;}/** * 返回鏈棧的長度 * @return */public int length(){return size;}/** * 進棧 * @param element */public void push(T element){// 讓top指向新建立的元素,新元素的next引用指向原來的棧頂元素top = new Node(element , top);size++;}/** * 出棧 * @return */public T pop(){Node oldTop = top;// 讓top引用指向原棧頂元素的下一個元素top = top.next;// 釋放原棧頂元素的next引用oldTop.next = null;size--;return oldTop.data;}/** * 訪問棧頂元素,但不刪除棧頂元素 * @return */public T peek(){return top.data;}/** * 判斷鏈棧是否為空白棧 * @return */public boolean empty(){return size == 0;}/** * 清空鏈棧 */public void clear(){// 將底層數組所有元素賦為nulltop = null;size = 0;}/** * 重寫toString方法 */public String toString(){// 鏈棧為空白鏈棧時if (empty()){return "[]";}else{StringBuilder sb = new StringBuilder("[");for (Node current = top ; current != null; current = current.next ){sb.append(current.data.toString() + ", ");}int len = sb.length();return sb.delete(len - 2 , len).append("]").toString();}}}

 

  2.線性結構之隊列的講解

    隊列也是一種被限制過的資料結構,它使用固定的一端來插入元素(隊尾),在另一端刪除相關的元素(隊頭)。

    其基本特徵為“先進先出”,而棧的基本特點為“先進後出”。

    在Java的jdk中主要的實作類別為Dqueue介面的實作類別ArrayDeque(線性)和LinkedList(鏈式),如果感興趣的話,請查相關的原始碼。

    首先講解的是隊列的線性儲存:

    具體內容請看相關代碼:

   

package com.yonyou.test;import java.util.Arrays;/** * 測試類別 * @author 小浩 * @建立日期 2015-3-20 */public class Test { public static void main(String[] args) {SequenceQueue<String> queue=new SequenceQueue<String>();System.out.println("隊列的初始化長度為:"+queue.length());queue.add("Hello");queue.add("World");queue.add("天下太平");System.out.println("當前stack中的元素為:"+queue);    queue.remove();System.out.println("當前stack中的元素為:"+queue);System.out.println("當前元素線性表是否為空白:"+queue.empty());} }/** * 建立一個儲存的線性隊列 * 注意這個類是線程不安全的,在多線程下不要使用 * @author 小浩 * @建立日期 2015-3-20 * @param <T> */class  SequenceQueue<T>{//線性隊列的預設長度private int DEFAULT_SIZE = 16;// 儲存數組的長度。private int capacity;// 定義一個數組用於儲存順序隊列的元素private Object[] elementData;// 儲存順序隊列中元素的當前個數private int front = 0;private int rear = 0;/** * 以預設數組長度建立空順序隊列 */public SequenceQueue(){capacity = DEFAULT_SIZE;elementData = new Object[capacity];}/** * 以一個初始化元素來建立順序隊列 * @param element */public SequenceQueue(T element){this();elementData[0] = element;rear++;}/** * 以指定長度的數組來建立順序隊列 * @param element 指定順序隊列中第一個元素 * @param initSize 指定順序隊列底層數組的長度 */public SequenceQueue(T element , int initSize){this.capacity = initSize;elementData = new Object[capacity];elementData[0] = element;rear++;}/** * 擷取順序隊列的大小 * @return */public int length(){return rear - front;}/** * 插入隊列 * @param element */public void add(T element){if (rear > capacity - 1){throw new IndexOutOfBoundsException("隊列已滿的異常");}elementData[rear++] = element;}/** * 移出隊列 * @return */@SuppressWarnings("unchecked")public T remove(){if (empty()){throw new IndexOutOfBoundsException("空隊列異常");}// 保留隊列的front端的元素的值T oldValue = (T)elementData[front];// 釋放隊列的front端的元素elementData[front++] = null;return oldValue;}/** * 返回隊列頂元素,但不刪除隊列頂元素 * @return */@SuppressWarnings("unchecked")public T element(){if (empty()){throw new IndexOutOfBoundsException("空隊列異常");}return (T)elementData[front];}/** * 判斷順序隊列是否為空白隊列 * @return */public boolean empty(){return rear == front;}/**清空順序隊列 *  */public void clear(){//將底層數組所有元素賦為nullArrays.fill(elementData , null);front = 0;rear = 0;}/** * 重寫toString方法 */public String toString(){if (empty()){return "[]";}else{StringBuilder sb = new StringBuilder("[");for (int i = front  ; i < rear ; i++ ){sb.append(elementData[i].toString() + ", ");}int len = sb.length();return sb.delete(len - 2 , len).append("]").toString();}}}

 

  其次講解的是隊列的線性儲存的迴圈組成:

     對於上面的非迴圈儲存可能會非常的浪費空間,下面我們將要建立一個對應的迴圈鏈表額概念,這樣的話可能會有效節約相應的空間。

     因為迴圈鏈表可以有效消除假滿的現象哦。

     廢話不在多說,請看代碼:

     

package com.yonyou.test;import java.util.Arrays;/** * 測試類別 * @author 小浩 * @建立日期 2015-3-20 */public class Test { public static void main(String[] args) {LoopQueue<String> queue=new LoopQueue<String>();System.out.println("隊列的初始化長度為:"+queue.length());queue.add("Hello");queue.add("World");queue.add("天下太平");System.out.println("當前stack中的元素為:"+queue);    queue.remove();System.out.println("當前stack中的元素為:"+queue);System.out.println("當前元素線性表是否為空白:"+queue.empty());} }/** * 建立一個順序儲存的迴圈線性隊列 * 注意這個類是線程不安全的,在多線程下不要使用 * @author 小浩 * @建立日期 2015-3-20 * @param <T> */class LoopQueue<T>{//迴圈隊列的預設長度為16private int DEFAULT_SIZE = 16;// 儲存數組的長度。private int capacity;// 定義一個數組用於儲存迴圈隊列的元素private Object[] elementData;// 儲存迴圈隊列中元素的當前個數private int front = 0;private int rear = 0;/** * 以預設數組長度建立空迴圈隊列 */public LoopQueue(){capacity = DEFAULT_SIZE;elementData = new Object[capacity];}/** * 以一個初始化元素來建立迴圈隊列 * @param element */public LoopQueue(T element){this();elementData[0] = element;rear++;}/** * 以指定長度的數組來建立迴圈隊列 * @param element 指定迴圈隊列中第一個元素 * @param initSize 指定迴圈隊列底層數組的長度 */public LoopQueue(T element , int initSize){this.capacity = initSize;elementData = new Object[capacity];elementData[0] = element;rear++;}/** * 擷取迴圈隊列的大小 * @return */public int length(){if (empty()){return 0;}return rear > front ? rear - front: capacity - (front - rear);}/** * 插入隊列 * @param element */public void add(T element){if (rear == front&& elementData[front] != null){throw new IndexOutOfBoundsException("隊列已滿的異常");}elementData[rear++] = element;// 如果rear已經到頭,那就轉頭rear = rear == capacity ? 0 : rear;}/** * 移出隊列 * @return */@SuppressWarnings("unchecked")public T remove(){if (empty()){throw new IndexOutOfBoundsException("空隊列異常");}// 保留隊列的front端的元素的值T oldValue = (T)elementData[front];// 釋放隊列的front端的元素elementData[front++] = null;// 如果front已經到頭,那就轉頭front = front == capacity ? 0 : front;return oldValue;}// 返回隊列頂元素,但不刪除隊列頂元素@SuppressWarnings("unchecked")public T element(){if (empty()){throw new IndexOutOfBoundsException("空隊列異常");}return (T)elementData[front];}// 判斷迴圈隊列是否為空白隊列public boolean empty(){//rear==front且rear處的元素為nullreturn rear == front&& elementData[rear] == null;}// 清空迴圈隊列public void clear(){// 將底層數組所有元素賦為nullArrays.fill(elementData , null);front = 0;rear = 0;}public String toString(){if (empty()){return "[]";}else{// 如果front < rear,有效元素就是front到rear之間的元素if (front < rear){StringBuilder sb = new StringBuilder("[");for (int i = front  ; i < rear ; i++ ){sb.append(elementData[i].toString() + ", ");}int len = sb.length();return sb.delete(len - 2 , len).append("]").toString();}// 如果front >= rear,有效元素為front->capacity之間、// 和0->front之間的元素else{StringBuilder sb = new StringBuilder("[");for (int i = front  ; i < capacity ; i++ ){sb.append(elementData[i].toString() + ", ");}for (int i = 0 ; i < rear ; i++){sb.append(elementData[i].toString() + ", ");}int len = sb.length();return sb.delete(len - 2 , len).append("]").toString();}}}}

 

  

 

      

    

 

   

  

 

  

  

 

   

   

   

   

Java資料結構之線性表(2)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.