棧是什麼?如果用生活中最常見的例子,我想到是書本的放置(當然這是部分人喜歡的做法)。但是給人的感覺是非常直接的,書本整齊跨一疊在一起,放在最上面的那本最先拿走,放在最底下那本書就最後拿走,形象吧,生活中有很多後進先出的栗子,就不一一說明了,用圖來說明應該很好理解。
放在最上面的那本書的位置叫棧頂,棧頂是可變的,比如說你拿走了西遊記,那麼棧頂就是紅樓夢得位置。相對應的棧底是不可操作的一端。
棧是一種特殊的線性表,特殊之處在於只能在一端對其進行操作,把元素放到棧中,這操作叫壓棧(push),壓棧之後,棧頂指標就向上移動。把元素從棧頂彈出,這叫出棧(pop),出棧後棧頂指標向下移動。訪問棧只能從棧頂元素進行。棧是很重要的資料結構,在很多演算法都有應用,比如圖的深度優先遍歷演算法(dfs),dijkstra演算法的中轉站。
棧的實現分為兩種,一是順序棧,用陣列來實現,二是鏈式棧,用指標將結點串聯起來,與鍊錶相似,但僅能在棧頂進行操作。
先實現簡單的順序棧,順序棧簡直不要太簡單,上**:
#ifndef staticstack_h
#define staticstack_h
template
<
typename t,
int n>
class
staticstack
bool
push
(const t& obj)
// 壓棧操作,就是往陣列增加乙個元素
return ret;
}bool
pop(
)// 出棧操作
return ret;}
t top()
// 獲取棧頂元素
void
clear()
// 把棧清空
intsize()
// 獲取棧的大小
~staticstack()
};#endif
來用一下這個簡單順序棧。記住,後進先出!
#include
#include
"staticstack.h"
using
namespace std;
intmain
(int argc,
const
char
* ar**)
// 入棧的時候是 0123456789 的順序
輸出正確。ok,順序棧就可以跳過了,因為順序棧的實現依賴於原生陣列,所以在定義的時候必須給定大小,並且在使用的過程中不能動態改變其大小,這是順序棧的乙個缺點,另外,當順序棧存放的元素是類型別,那麼在定義順序棧時就會自動呼叫類的建構函式,有多少個元素就會呼叫多少次,這樣做顯然會降低效率,所以順序棧的使用相對較少。
現在重點來實現鏈式棧吧,有了順序棧的基礎,實現鏈式棧也相當容易。
直接上**:
#ifndef linkstack_h
#define linkstack_h
template
<
typename t>
class
linkstack
;mutable node header;
// 使用頭節點會方便各種操作
int m_size;
public
:linkstack()
bool
push
(const t& obj)
// 壓棧操作
else
return ret;
}bool
pop(
)// 出棧操作
else
return ret;}
t top()
const
// 獲取棧頂元素
intsize()
const
void
clear()
// 清空棧}~
linkstack()
};#endif
僅僅是實現乙個棧好像沒有什麼好玩的,順序棧操作乙個陣列,鏈式就幾個指標操作。現在用棧來實現乙個掃瞄函式,將字串中的左右符號進行匹配。舉個栗子,「( a k)」,這樣乙個看起來複雜l凌亂的字串,怎麼知道它的左右符號匹不匹配呢?人工智慧嘛,人工來數一下不就可以了嗎?good idea!簡單的數幾分鐘就應該知道結果了,要是一本書那麼多的字串怎麼來數?當然是把工作交給計算機!寫個程式來檢查左右符號是否匹配不就得了。主要注意的地方是左符號、右符號以及引號的處理,其他字元直接忽略。知道重點了,實現就容易了,說幹就幹,動手!
#include
#include
"linkstack.h"
// 需要提前準備相應的輔助函式
bool
is_left
(const
char c)
// 判斷是否為左符號
bool
is_right
(const
char c)
// 判斷是否為右符號')
||(c ==
'>')||
(c ==
']');}
bool
is_quot
(const
char c)
// 判斷是否為引號
bool
is_match
(const
char l,
const
char r)
// 進行匹配判斷')
)||((l ==
'[')
&&(r ==
']'))||
((l ==
'(r ==
'>'))
||((l ==
'\'')&&
(r ==
'\''))
||((l ==
'\"')&&
(r ==
'\"'))
;return ret;
}bool
scan_func
(const
char
* str)
// 掃瞄字串的函式
elseif(
is_right
(str[i]))
// 右符號,判斷棧是否為空
else
}elseif(
is_quot
(str[i]))
// 引號判斷
// 與棧頂元素匹配,那就將棧頂的引號出棧
elseif(
is_match
(stack.
top(
), str[i]))
}}return
(ret &&
(stack.
size()
==0))
;}intmain
(int argc,
const
char
* ar**)
] ) > "
;const
char
* str2 =
" \" \' 123 \' \" "
;const
char
* str3 =
"< 123 "
; cout << endl;
cout << str1 <<
" result of match : "
<<
(scan_func
(str1)
?" true "
:" false "
)<< endl;
cout << endl;
cout << str2 <<
" result of match : "
<<
(scan_func
(str2)
?" true "
:" false "
)<< endl;
cout << endl;
cout << str3 <<
" result of match : "
<<
(scan_func
(str3)
?" true "
:" false "
)<< endl;
return0;
}
看看輸出結果,多easy,要是用人工的智慧型來數,得花點點點時間。
C 棧 後進先出 佇列實現與解析
stack 集合類實現了 後入先出的棧 也是一種線性表 所有的插入 push 和刪除 pop 通常還有所有的訪問 都在頂部進行。queue 集合類實現了 先入先出佇列 也是一種線性表 所有的插入 enqueue 都在佇列 表 的佇列最末端 進行,所有刪除 dequeue 通常還有所有的訪問 都在佇列...
資料結構 實現棧
include include include define node len sizeof node 1 pstack ptop pstack pbottom都指向節點 typedef struct node pnode,node typedef struct stack pstack,stack...
資料結構 棧實現
棧和佇列不一樣,棧是後進先出。實現時用了陣列儲存棧,陣列大小根據內容自動擴充。廢話不多說,上 c mystack.h pragma once templateclass mystack templateint mystack getcount templatet mystack top templa...