1. 程式人生 > >棧的順序儲存結構及實現

棧的順序儲存結構及實現

棧和佇列:

前面已經介紹完了線性表的順序和鏈式兩中實現,但如果再對線性表增加一些額外的限制和約束,例如,去除普通線性表中通過索引訪問資料元素的功能,去除普通線性表中查詢某個元素在表中的位置的功能。去除普通線性表中可以在任意位置隨意增加、刪除元素的功能,而是改為只允許線上性表的某端新增、刪除元素,這時候普通線性表就會變成另外兩種特殊的線性表:棧和佇列。

從邏輯上看,棧和佇列其實是由普通的線性表發展而來的,為普通線性表增加一些特殊的限制就可以得到棧和隊列了。從功能上來看,棧和佇列比普通線性表的功能相對弱一些,但在一些特殊的場合下,使用棧和佇列會更有利,例如,編譯器實現函式呼叫時需要使用棧來儲存斷點,實現遞迴演算法時也需要使用棧來儲存。當然我這裡最主要是因為考慮到後面會有樹的深度優先演算法和廣度優先演算法打下基礎。

棧是一種資料結構,他代表只能在某一端進行插入、刪除操作的特殊線性表,通常就是線上性表的尾端進行插入、刪除操作。
對於棧而言,允許進行插入、刪除操作的一端被稱為棧頂(top),另一端則被稱為棧底(bottom)。
如果一個棧不包含任何元素,那麼這個棧就被稱為空棧。
從棧頂插入一個元素被稱為進棧或者入棧或者壓棧,對應的英文說法為 push。
從棧頂刪除一個元素被稱為出棧或者退棧,對應的英文說法為 pop。
如下圖為棧的操作示意圖:

對於a0,a1,a2,……,an-1的棧,假設棧中元素按a0,a1,a2,……,an-1的次序進棧,那麼a0為棧的棧底元素,an-1為棧頂元素。出棧時
第一個彈出的元素為棧頂元素,也就是an-1、也就是說棧中的元素的修改是按後進先出(LIFO)的原則進行的。

歸納起來,可以再對棧下一個定義:棧是一種後進先出(LIFO)的線性表。

棧的常用操作:
棧是一種被限制的線性表,通常不應該提供線性表中的如下操作:
(1)、獲取指定索引處的元素。
(2)、按值查詢資料元素的位置。
(3)、向指定索引位置插入元素。
(4)、刪除指定索引位置處的元素。
從上面這些方法可以看出,棧不應提供從中間任意位置訪問元素的方法。也就是說,棧只允許從棧頂插入、刪除元素。

棧的常用操作如下:
(1)、初始化:通常是一個構造器,用於建立一個空棧。
(2)、返回棧的長度:該方法用於返回棧中資料元素的長度。
(3)、入棧

:向棧的棧頂插入一個數據元素,棧的長度 +1。
(4)、出棧:向棧的棧頂刪除一個數據元素,棧的長度 -1。返回被刪除的元素
(5)、訪問棧頂元素:返回棧頂的資料元素,但不刪除。
(6)、判斷棧是否為空棧:該方法判斷棧是否為空,如果為空則返回ture,否則則返回false。
(7)、清空棧:將棧清空。
對於棧而言,上面的加粗的部分就是他的標誌性方法。

順序儲存結構的棧簡稱為順序棧,它利用一組地址連續的儲存單元依次存放從棧底到棧頂的資料元素。棧底位置固定不變,他的棧頂元素可以直接通過順序棧底層陣列的陣列元素arr[size - 1]來訪問。順序棧的儲存結構示意圖如下:

1、進棧
對於順序棧的進棧操作而言,只需將新的元素存入棧內,然後讓記錄棧的元素個數的size + 1。程式即可再次通過arr[size - 1]重新訪問新的棧頂元素。進棧操作如下示意圖:

由於順序棧底層通常採用陣列來儲存資料元素,因此可能出現的情況是:當程式試圖讓一個數據元素進棧,底層陣列已滿,那麼就必須擴充底層陣列的長度來容納

新的進棧的資料元素。

2、出棧
對於順序棧的出棧操作而言,需要將棧頂的元素彈出,程式要做兩件事:
(1)讓記錄棧內元素個數的變數size-1。
(2)釋放陣列對棧頂元素的引用。
出棧操作示意圖如下:

對於刪除操作而言,只要讓記錄棧內元素個數的size - 1,程式即可通過arr[size - 1]訪問到新的棧的棧頂元素。但不要忘記釋放原來棧頂元素的陣列索引。
否則會引起記憶體洩漏。

下面是程式碼實現:

import java.util.Arrays;

public class SequenceStack<T> {
	private final int DEFAULT_SIZE = 10;
	//棧的容量
	private int capacity;
	//底層存放資料元素的陣列
	private Object[] elementData;
	//當前棧所存放的元素個數
	private int size = 0;
	
	//預設陣列擴容向左移一位
	private int capacityIncrementInt = 1;
	//初始化1
	public SequenceStack(){
		capacity = DEFAULT_SIZE;
		elementData = new Object[capacity];
	}
	//初始化2
	public SequenceStack(T element){
		/*capacity = DEFAULT_SIZE;
		elementData = new Object[capacity];*/
		this();
		elementData[0] = element;
		size ++;
	}
	//初始化3
	public SequenceStack(T element, int initCapacity){
		capacity = initCapacity;
		elementData = new Object[capacity];
		elementData[0] = element;
		size ++;
	}
	//初始化4
	public SequenceStack(T element, int initCapacity, int initCapacityIncrementInt){
		this(element, initCapacity);
		capacityIncrementInt = initCapacityIncrementInt;
	}
	//返回元素個數
	public int length(){
		return size;
	}
	//是否為空棧
	public boolean isEmpty(){
		return size == 0;
	}
	
	//位運算擴容,很麻煩,而且效能差
	private void expendCapacity(int minCapacity){
		while(capacity < minCapacity){
			capacity <<= capacityIncrementInt;
		}
		elementData = Arrays.copyOf(elementData, capacity);
	}
	
	//入棧
	public void push(T element){
		expendCapacity(size + 1);
		elementData[size] = element;
		size ++;
	}
	
	//出棧
	@SuppressWarnings("unchecked")
	public T pop(){
		T t = (T) elementData[size - 1];
		elementData[size - 1] = null;
		size --;
		return t;
	}
	
	//返回棧頂元素,但不刪除
	@SuppressWarnings("unchecked")
	public T peek(){
		return (T) elementData[size - 1];
	}
	
	//清空棧
	public void clear(){
		if(size > 0){
			/*for(int i = 0; i < size; i ++){
				elementData[i] = null;
			}*/
			Arrays.fill(elementData, null);
			size = 0;
		}
	}
	
	//toString方法
	public String toString(){
		if(size == 0){
			return "[]";
		}else{
			StringBuffer sb = new StringBuffer("[");
			for(int i = 0; i < size; i ++){
				sb.append(elementData[i].toString() + ",");
			}
			return sb.toString().substring(0, sb.length() - 1) + "]";
		}
		
	}
}

從上面的程式可以看出,當採用基於陣列的方式來實現順序棧時,程式比普通線性表更簡單。這符合前面的介紹:從功能上來看,棧比普通線性表的功能更弱;棧是一種被限制過得線性表,只能從棧頂插入、刪除元素。


測試類如下:
import com.yc.list.SequenceStack;

public class SequenceStackTest {
	public static void main(String[] args) {
		SequenceStack<Student> stack = new SequenceStack<Student>();
		stack.push(new Student("WB", "湖工", 20));
		stack.push(new Student("LS", "湖工", 22));
		stack.push(new Student("QYB", "湖工", 21));
		System.out.println( "PUSh後的棧為:  " + stack.toString());
		
		Student speek = stack.peek();
		System.out.println("peek的資料元素:  "+speek.toString());
		System.out.println("peek後的棧為:  "+stack.toString());
		
		Student spop1 = stack.pop();
		System.out.println( "pop的資料元素:   "+spop1);
		System.out.println( "pop後的棧為:   "+stack.toString());
		
		Student spop2 = stack.pop();
		System.out.println( "pop的資料元素:   "+spop2);
		System.out.println( "pop後的棧為:   "+stack.toString());
	}
}
輸出結果:

相關推薦

順序儲存結構實現

棧和佇列: 前面已經介紹完了線性表的順序和鏈式兩中實現,但如果再對線性表增加一些額外的限制和約束,例如,去除普通線性表中通過索引訪問資料元素的功能,去除普通線性表中查詢某個元素在表中的位置的功能。去除普通線性表中可以在任意位置隨意增加、刪除元素的功能,而是改為只允許線上性表

資料結構:線性表的順序儲存結構實現

線性表的順序儲存結構——順序表 線性表的順序儲存結構稱為順序表 順序表的實現 const int MaxSize=100; template<class DataType> class SeqList { public: SeqList(){lengt

資料結構(c語言)——鏈儲存結構實現

鏈棧:就是一種特殊的單鏈表,FILO(先進後出) 通常對於連結串列來說: 1.是不需要頭節點的。 2.基本不存在滿棧的情況,除非記憶體已沒有可用的空間。   不多bibi你們都懂哈,直接上程式碼:  鏈棧結構: typedef struct Stock

順序表(線性表的順序儲存結構)C語言實現

1.邏輯結構上呈線性分佈的資料元素在實際的物理儲存結構中也同樣相互之間緊挨著,這種儲存結構稱為線性表的順序儲存結構。 也就是說,邏輯上具有線性關係的資料按照前後的次序全部儲存在一整塊連續的記憶體空間中,之間不存在空隙,這樣的儲存結構稱為順序儲存結構。使用順序儲存結構儲存的資料,第一個元素所在的地

資料結構(c語言)——順序佇列儲存結構實現

使用迴圈佇列,避免出現偽滿佇列的情況 判斷佇列為空的條件:rear == front; 判斷佇列為滿的條件:(rear+1)%MAXSIZE == front; 空出一個數組元素空間,用以區別開來滿佇列和空佇列。 一個順序佇列的結構:  typedef struc

【資料結構作業三】利用(以順序儲存結構實現二、十和十六進位制轉換

#include <iostream> #define MAXSIZE 100 using namespace std; typedef int SElemType; typedef struct { SElemType *base; SElemType

資料結構(c語言)——鏈佇列儲存結構實現

是佇列鴨,FIFO,先進先出! 對於帶頭節點的和不帶頭節點的鏈佇列的操作有個小小的區別: 不帶頭結點的鏈佇列在入佇列的時候,第一個元素時要先判斷是否為空,再插入。而帶頭結點不需要,操作更方便些;  我是分割線-----------------------------

二叉樹的鏈式儲存結構實現(C語言完整程式碼+詳細註釋)

鏈式儲存結構儲存二叉樹,實際上就是採用連結串列儲存二叉樹。 既然是使用連結串列,首先需要構建連結串列中節點的結構。考慮到儲存物件為二叉樹,其各個節點最多包含 3 部分,依次是:左孩子、節點資料和右孩子,因此,連結串列的每個節點都由這 3 部分組成: 圖 1 二叉連結串列結點構成 圖 1 中,Lchi

二叉樹的順序儲存原理實現過程

二叉樹的順序儲存,實際上就是使用陣列儲存二叉樹。 使用陣列儲存二叉樹的實現思想是將二叉樹從根節點按照層次順序依次儲存在陣列中,但需要注意的是,此方式只適用於完全二叉樹,如果要使用陣列儲存普通二叉樹,需要提前將該二叉樹轉化為完全二叉樹。 完全二叉樹,即二叉樹除了最後一層節點外,其餘各節點都既有左節點和右節點

佇列的鏈式儲存結構實現

佇列的鏈式儲存結構,其實就是線性表的單鏈表,只不過它只是尾進頭出而已,我們把它簡稱為鏈佇列。為了操作上的方便,我們將隊頭指標指向鏈佇列的頭結點,而隊尾指標指向終端節點。如果 空佇列時,front和rear都指向頭結點。 入隊操作: 在隊尾新增元素,先將隊尾元素的n

資料結構之旅(一)順序儲存結構實現線性表

用陣列(順序儲存結構)來實現線性表 該資料結構具有如下功能: 初始化 獲取資料 在表尾新增資料 彈出表尾資料 設定指定位置資料 刪除指定位置資料 在指定位置插入資料 優點 1、無須為表示表中元素之間的邏輯關係而增加額外的儲存空間 2、可以快速地存取表中任一位置的元素

(1)順序表的操作 ① 輸入一組整型元素序列,建立線性表的順序儲存結構。 ② 實現該線性表的遍歷。 ③ 在該順序表中查詢某一元素,查詢成功顯示查詢元素,否則顯示查詢失敗。 ④ 在該順序表中刪除或插入指

(1)順序表的操作 ① 輸入一組整型元素序列,建立線性表的順序儲存結構。 ② 實現該線性表的遍歷。 ③ 在該順序表中查詢某一元素,查詢成功顯示查詢元素,否則顯示查詢失敗。 ④ 在該順序表中刪除或插入指定元素。 ⑤ 建立兩個按值遞增有序的順序表,將他們合併成一個按值遞增有序的

線性表的順序儲存結構結構的插入與刪除

順序儲存定義 線性表的順序儲存結構,指的是用一段地址連續的儲存單元依次儲存線性表的資料元素。 順序儲存方式 線性表的順序儲存結構,就是在記憶體中找了塊地兒,通過站位的形式,把

串的定長順序儲存結構實現串的基本操作Replace(&S,T,V)

編寫演算法,實現串的基本操作Replace(&S,T,V)。要求採用以下所定義的定長順序儲存表示,但不允許呼叫串的基本操作。 定長順序串SString的型別定義:typedef unsigned char SString[MAXSTRLEN+1]; /* s[0

【資料結構順序儲存結構 C語言實現

棧(stack),是一種線性儲存結構,它有以下幾個特點: 棧中資料是按照"後進先出(LIFO, Last In First Out)"方式進出棧的。 向棧中新增/刪除資料時,只能從棧頂進行操作。 基本操作 initStack(&S) destroySt

Java中實現(1)-使用順序儲存結構(陣列)以及實現

棧和佇列其實是與普通的線性發展而來的,為普通的線性表增加一些特殊的限制就可以得到棧和隊列了。從功能上看,棧和佇列比普通的線性表功能相對弱一點,但是在特殊的場合下,使用棧和佇列更有利,例如,編譯器在實現函式的呼叫的時候需要使用棧來儲存斷點,實現遞迴演算法時候也需要用棧來儲存。

資料結構和佇列(五)順序儲存結構和鏈式儲存結構實現

一、 實驗目的1. 熟悉棧的特點(先進後出)及棧的抽象類定義;2. 掌握棧的順序儲存結構和鏈式儲存結構的實現;3. 熟悉佇列的特點(先進先出)及佇列的抽象類定義;4. 掌握棧的順序儲存結構和鏈式儲存結構的實現;二、實驗要求1. 複習課本中有關棧和佇列的知識;2. 用C++語言

順序儲存結構 -- C++使用類模板實現

棧 棧是先進後出的線性表。即限定只能在表的一段進行插入和刪除操作的線性表。 棧結構在計算機中有廣泛的應用。常見的軟體的”撤銷”和”恢復”功能就是用棧實現的。 棧的順序儲存結構示例程式碼 template<typename T> cla

順序儲存結構——順序 圖解和程式碼實現

棧的順序儲存結構稱為順序棧 先看下順序棧的圖片: SeqStack.h //SeqStack.h #ifndef SEQSTACK_H #define SEQSTACK_H const int StackSize=10; //10只是示例性的資料,可以根據實際問題

【資料結構】【二】陣列實現的線性表(線性表的順序儲存結構)

資料結構 陣列實現線性表 通過陣列實現了一個簡單的線性表 功能: 在陣列尾部新增元素 在陣列指定位置新增元素 根據下標獲取元素 根據下標刪除元素 根據元素刪除元素 獲取當前陣列長度 判斷當前陣列是否為空 列印陣列元素 public