後進者先出,先進者後出,這就是典型的「棧」結構。
從棧的操作特性上來看,棧是一種「操作受限」的線性表,只允許在一端插入和刪除資料。但這種受限,也控制了出錯的概率。
當某個資料集合只涉及在一端插入和刪除資料,並且滿足後進先出、先進後出的特性,我們就應該首選「棧」這種資料結構。
從棧的定義看,棧主要包含兩個操作,入棧和出棧,也就是在棧頂插入乙個資料和從棧頂刪除乙個資料。
如何用**實現乙個棧?
實際上,棧既可以用陣列來實現,也可以用鍊錶來實現。用陣列實現的棧,我們叫作順序棧,用鍊錶實現的棧,我們叫作鏈式棧。
使用c語言實現棧的**如下:(****於《c語言實現棧**》)
/*
棧的特性:先進後出。
棧在計算語言處理和將遞迴演算法改為非遞迴演算法等方面起著非常重要的作用。
*/#define initsize 100
//儲存空間的初始分配量
typedef
int elemtype;
typedef
struct
sqstack;
//初始化操作
//建立乙個空棧,棧頂指標top初始化為0
void
initstack
(sqstack *s)
//求棧長操作
intgetlen
(sqstack *s)
//取棧頂元素操作
//將棧頂元素值存入e指向的記憶體單位,top值不變
intgettop
(sqstack *s,elemtype *e)
//壓棧操作
//將入棧元素x存入top所指的位置上,然後棧頂指標top增1
intpush
(sqstack *s,elemtype x)
s->base[s->top++
]= x;
return1;
}//彈棧操作
//先將棧頂指標top減1,再將top單元中的元素存入指標e所指向的記憶體單元
intpop
(sqstack *s,elemtype *e)
//判棧s是否為空
intemptystack
(sqstack *s)
//輸出棧操作
void
list
(sqstack *s)
printf
("\n");
}
不管是順序棧還是鏈式棧,我們儲存資料只需要乙個大小為 n 的陣列就夠了。在入棧和出棧過程中,只需要一兩個臨時變數儲存空間,所以空間複雜度是 o(1)。
注意,這裡儲存資料需要乙個大小為 n 的陣列,並不是說空間複雜度就是 o(n)。因為,這 n 個空間是必須的,無法省掉。所以我們說空間複雜度的時候,是指除了原本的資料儲存空間外,演算法執行還需要額外的儲存空間。
不管是順序棧還是鏈式棧,入棧、出棧只涉及棧頂個別資料的操作,所以時間複雜度都是 o(1)。
leetcode上關於棧的題目
資料結構與演算法解析 佇列篇
先進者先出,這就是典型的 佇列 佇列跟棧非常相似,支援的操作也很有限,也是一種操作受限的線性表資料結構。最基本的操作也是兩個 跟棧一樣,佇列可以用陣列來實現,也可以用鍊錶來實現。用陣列實現的棧叫作順序棧,用鍊錶實現的棧叫作鏈式棧。同樣,用陣列實現的佇列叫作順序佇列,用鍊錶實現的佇列叫作鏈式佇列。2....
資料結構與演算法解析 「遞迴」篇
遞迴,在數學與電腦科學中,是指在函式的定義中使用函式自身的方法。也就是說,遞迴演算法是一種直接或者間接呼叫自身函式或者方法的演算法。遞迴是一種應用非常廣泛的演算法 或者程式設計技巧 很多資料結構和演算法的編碼實現都要用到遞迴,比如 dfs 深度優先搜尋 前中後序二叉樹遍歷等等。去的過程叫 遞 回來的...
資料結構與演算法解析 鍊錶篇
鍊錶是一種物理儲存單元上非連續 非順序的儲存結構,資料元素的邏輯順序是通過鍊錶中的指標鏈結次序實現的。鍊錶由一系列結點 鍊錶中每乙個元素稱為結點 組成,結點可以在執行時動態生成。每個結點包括兩個部分 乙個是儲存資料元素的資料域,另乙個是儲存下乙個結點位址的指標域 對於雙向鍊錶也會儲存上乙個節點的位址...