Go語言中沒有佇列和棧相關的資料結構;但可以藉助切片來實現棧與佇列的操作。go語言實現棧和佇列主要用到append和切片(用內建陣列型別進行操作),建立棧和佇列的語法「make([]int, 0)」,入棧和入隊的語法「append(stack, 10)」,出棧的語法「v:=stack[len(stack)-1] stack = stack[:len(stack)-1]」。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
go語言中,並沒有棧與佇列相關的資料結構,但是我們可以藉助切片來實現棧與佇列的操作;接下來我們一起實現棧與佇列基本操作,並且還會實現用棧實現佇列,用佇列實現棧的操作。
go語言實現棧和佇列主要用到append 和切片(用內建陣列型別進行操作)
//建立棧
stack := make([]int, 0)
//push壓入棧
stack = append(stack, 10)
//pop彈出
v := stack[len(stack)-1]
stack = stack[:len(stack)-1]
//檢查棧空
len(stack) == 0
登入後複製
//建立佇列
queue := make([]int, 0)
//enqueue入隊
queue = append(queue, 10)
//dequeue出隊
v := queue[0]
queue = queue[1:]
//檢查佇列為空
len(queue) == 0
登入後複製
使用棧來模式佇列的行為,如果僅僅用一個棧,是一定不行的,所以需要兩個棧一個輸入棧,一個輸出棧,這裡要注意輸入棧和輸出棧的關係。
下面動畫模擬以下佇列的執行過程如下:
執行語句:
queue.push(1);
queue.push(2);
queue.pop(); 注意此時的輸出棧的操作
queue.push(3);
queue.push(4);
queue.pop();
queue.pop();注意此時的輸出棧的操作
queue.pop();
queue.empty();
登入後複製
在push資料的時候,只要資料放進輸入棧就好,但在pop的時候,操作就複雜一些,輸出棧如果為空,就把進棧資料全部匯入進來(注意是全部匯入),再從出棧彈出資料,如果輸出棧不為空,則直接從出棧彈出資料就可以了。
最後如何判斷佇列為空呢?如果進棧和出棧都為空的話,說明模擬的佇列為空了。
接下來看一下LeetCode原題
請你僅使用兩個棧實現先入先出佇列。佇列應當支援一般佇列支援的所有操作(push、pop、peek、empty):
實現 MyQueue 類:
void push(int x) 將元素 x 推到佇列的末尾 int pop() 從佇列的開頭移除並返回元素 int peek() 返回佇列開頭的元素 boolean empty() 如果佇列為空,返回 true ;否則,返回 false 說明:
你 只能 使用標準的棧操作 —— 也就是隻有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的語言也許不支援棧。你可以使用 list 或者 deque(雙端佇列)來模擬一個棧,只要是標準的棧操作即可。
解決這個問題,需要一個輸出棧和輸入棧
先將資料放到輸入棧,再把資料從輸入棧放到輸出棧,此時輸出棧輸出資料的順序就和佇列一樣了,先入先出
type MyQueue struct {
stackIn []int // 用來儲存Push資料
stackOut []int // 用來儲存Pop資料
}
// 棧構造器
func Constructor() MyQueue {
return MyQueue{
stackIn: make([]int, 0),
stackOut: make([]int, 0),
}
}
func (this *MyQueue) Push(x int) {
// 判斷stackOut中是否有元素,有的話全部放到stackIn
for len(this.stackOut) != 0 {
val := this.stackOut[len(this.stackOut)-1]
this.stackOut = this.stackOut[:len(this.stackOut)-1]
this.stackIn = append(this.stackIn, val)
}
// 將資料加進stackIn
this.stackIn = append(this.stackIn, x)
}
func (this *MyQueue) Pop() int {
// 判斷stackIn中是否有元素,有的話全部放到stackOut
for len(this.stackIn) != 0 {
val := this.stackIn[len(this.stackIn)-1]
this.stackIn = this.stackIn[:len(this.stackIn)-1]
this.stackOut = append(this.stackOut, val)
}
// stackOut為零,說明沒有元素,return 0
if len(this.stackOut) == 0 {
return 0
}
// stackOut Pop 元素
res := this.stackOut[len(this.stackOut)-1]
this.stackOut = this.stackOut[:len(this.stackOut)-1]
return res
}
func (this *MyQueue) Peek() int {
// 呼叫Pop()方法
val := this.Pop()
// val為零,說明沒有元素,return 0
if val == 0 {
return 0
}
// Pop()方法刪除了val,這裡加上
this.stackOut = append(this.stackOut, val)
return val
}
func (this *MyQueue) Empty() bool {
// 兩個棧都為空,說明為空,否則不為空
return len(this.stackOut) == 0 && len(this.stackIn) == 0
}
登入後複製
程式碼可以直接拿到力扣上執行。我已經將細節全部用註釋解釋了,如果不懂可以私信博主。
佇列模擬棧,其實一個佇列就夠了,那麼我們先說一說兩個佇列來實現棧的思路。
佇列是先進先出的規則,把一個佇列中的資料匯入另一個佇列中,資料的順序並沒有變,並沒有變成先進後出的順序。
所以用棧實現佇列, 和用佇列實現棧的思路還是不一樣的,這取決於這兩個資料結構的性質。
但是依然還是要用兩個佇列來模擬棧,只不過沒有輸入和輸出的關係,而是另一個佇列完全用又來備份的!
如下面動畫所示,用兩個佇列que1和que2實現佇列的功能,que2其實完全就是一個備份的作用,把que1最後面的元素以外的元素都備份到que2,然後彈出最後面的元素,再把其他元素從que2導回que1。
模擬的佇列執行語句如下:
queue.push(1);
queue.push(2);
queue.pop(); // 注意彈出的操作
queue.push(3);
queue.push(4);
queue.pop(); // 注意彈出的操作
queue.pop();
queue.pop();
queue.empty();
登入後複製
接下來看一下LeetCode原題
請你僅使用兩個佇列實現一個後入先出(LIFO)的棧,並支援普通棧的全部四種操作(push、top、pop 和 empty)。
實現 MyStack 類:
void push(int x) 將元素 x 壓入棧頂。 int pop() 移除並返回棧頂元素。 int top() 返回棧頂元素。 boolean empty() 如果棧是空的,返回 true ;否則,返回 false 。
注意:
你只能使用佇列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 這些操作。 你所使用的語言也許不支援佇列。 你可以使用 list (列表)或者 deque(雙端佇列)來模擬一個佇列 , 只要是標準的佇列操作即可。
用兩個佇列que1和que2實現佇列的功能,que2其實完全就是一個備份的作用,把que1最後面的元素以外的元素都備份到que2,然後彈出最後面的元素,再把其他元素從que2導回que1。
type MyStack struct {
//建立兩個佇列
queue1 []int
queue2 []int
}
func Constructor() MyStack {
return MyStack{ //初始化
queue1:make([]int,0),
queue2:make([]int,0),
}
}
func (this *MyStack) Push(x int) {
//先將資料存在queue2中
this.queue2 = append(this.queue2,x)
//將queue1中所有元素移到queue2中,再將兩個佇列進行交換
this.Move()
}
func (this *MyStack) Move(){
if len(this.queue1) == 0{
//交換,queue1置為queue2,queue2置為空
this.queue1,this.queue2 = this.queue2,this.queue1
}else{
//queue1元素從頭開始一個一個追加到queue2中
this.queue2 = append(this.queue2,this.queue1[0])
this.queue1 = this.queue1[1:] //去除第一個元素
this.Move() //重複
}
}
func (this *MyStack) Pop() int {
val := this.queue1[0]
this.queue1 = this.queue1[1:] //去除第一個元素
return val
}
func (this *MyStack) Top() int {
return this.queue1[0] //直接返回
}
func (this *MyStack) Empty() bool {
return len(this.queue1) == 0
}
登入後複製
其實這道題目就是用一個佇列就夠了。
一個佇列在模擬棧彈出元素的時候只要將佇列頭部的元素(除了最後一個元素外) 重新新增到佇列尾部,此時在去彈出元素就是棧的順序了。
type MyStack struct {
queue []int//建立一個佇列
}
/** Initialize your data structure here. */
func Constructor() MyStack {
return MyStack{ //初始化
queue:make([]int,0),
}
}
/** Push element x onto stack. */
func (this *MyStack) Push(x int) {
//新增元素
this.queue=append(this.queue,x)
}
/** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
n:=len(this.queue)-1//判斷長度
for n!=0{ //除了最後一個,其餘的都重新新增到佇列裡
val:=this.queue[0]
this.queue=this.queue[1:]
this.queue=append(this.queue,val)
n--
}
//彈出元素
val:=this.queue[0]
this.queue=this.queue[1:]
return val
}
/** Get the top element. */
func (this *MyStack) Top() int {
//利用Pop函數,彈出來的元素重新新增
val:=this.Pop()
this.queue=append(this.queue,val)
return val
}
/** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
return len(this.queue)==0
}
登入後複製
【相關推薦:Go視訊教學、】
以上就是Go語言有佇列和棧結構嗎的詳細內容,更多請關注TW511.COM其它相關文章!