溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Go語言有沒有隊(duì)列和棧結(jié)構(gòu)

發(fā)布時間:2023-01-05 09:37:41 來源:億速云 閱讀:121 作者:iii 欄目:編程語言

這篇文章主要介紹“Go語言有沒有隊(duì)列和棧結(jié)構(gòu)”,在日常操作中,相信很多人在Go語言有沒有隊(duì)列和棧結(jié)構(gòu)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Go語言有沒有隊(duì)列和棧結(jié)構(gòu)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

Go語言中沒有隊(duì)列和棧相關(guān)的數(shù)據(jù)結(jié)構(gòu);但可以借助切片來實(shí)現(xiàn)棧與隊(duì)列的操作。go語言實(shí)現(xiàn)棧和隊(duì)列主要用到append和切片(用內(nèi)置數(shù)組類型進(jìn)行操作),創(chuàng)建棧和隊(duì)列的語法“make([]int, 0)”,入棧和入隊(duì)的語法“append(stack, 10)”,出棧的語法“v:=stack[len(stack)-1] stack = stack[:len(stack)-1]”。

go語言中,并沒有棧與隊(duì)列相關(guān)的數(shù)據(jù)結(jié)構(gòu),但是我們可以借助切片來實(shí)現(xiàn)棧與隊(duì)列的操作;接下來我們一起實(shí)現(xiàn)棧與隊(duì)列基本操作,并且還會實(shí)現(xiàn)用棧實(shí)現(xiàn)隊(duì)列,用隊(duì)列實(shí)現(xiàn)棧的操作。

實(shí)現(xiàn)棧與隊(duì)列基本操作

1、?;静僮?/strong>

go語言實(shí)現(xiàn)棧和隊(duì)列主要用到append 和切片(用內(nèi)置數(shù)組類型進(jìn)行操作)

//創(chuàng)建棧
stack := make([]int, 0)
//push壓入棧
stack = append(stack, 10)
//pop彈出
v := stack[len(stack)-1]
stack = stack[:len(stack)-1]
//檢查???
len(stack) == 0

2、隊(duì)列基本操作

//創(chuàng)建隊(duì)列
queue := make([]int, 0)
//enqueue入隊(duì)
queue = append(queue, 10)
//dequeue出隊(duì)
v := queue[0]
queue = queue[1:]
//檢查隊(duì)列為空
len(queue) == 0

用棧實(shí)現(xiàn)隊(duì)列

1、理論

使用棧來模式隊(duì)列的行為,如果僅僅用一個棧,是一定不行的,所以需要兩個棧一個輸入棧,一個輸出棧,這里要注意輸入棧和輸出棧的關(guān)系。

下面動畫模擬以下隊(duì)列的執(zhí)行過程如下:

執(zhí)行語句:

queue.push(1);
queue.push(2);
queue.pop(); 注意此時的輸出棧的操作
queue.push(3);
queue.push(4);
queue.pop();
queue.pop();注意此時的輸出棧的操作
queue.pop();
queue.empty();

在push數(shù)據(jù)的時候,只要數(shù)據(jù)放進(jìn)輸入棧就好,但在pop的時候,操作就復(fù)雜一些,輸出棧如果為空,就把進(jìn)棧數(shù)據(jù)全部導(dǎo)入進(jìn)來(注意是全部導(dǎo)入),再從出棧彈出數(shù)據(jù),如果輸出棧不為空,則直接從出棧彈出數(shù)據(jù)就可以了。

最后如何判斷隊(duì)列為空呢?如果進(jìn)棧和出棧都為空的話,說明模擬的隊(duì)列為空了。

2、算法題

接下來看一下LeetCode原題

232. 用棧實(shí)現(xiàn)隊(duì)列

請你僅使用兩個棧實(shí)現(xiàn)先入先出隊(duì)列。隊(duì)列應(yīng)當(dāng)支持一般隊(duì)列支持的所有操作(push、pop、peek、empty):

實(shí)現(xiàn) MyQueue 類:

void push(int x) 將元素 x 推到隊(duì)列的末尾 int pop() 從隊(duì)列的開頭移除并返回元素 int peek() 返回隊(duì)列開頭的元素 boolean empty() 如果隊(duì)列為空,返回 true ;否則,返回 false 說明:

你 只能 使用標(biāo)準(zhǔn)的棧操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。 你所使用的語言也許不支持棧。你可以使用 list 或者 deque(雙端隊(duì)列)來模擬一個棧,只要是標(biāo)準(zhǔn)的棧操作即可。

3、思路

解決這個問題,需要一個輸出棧和輸入棧

先將數(shù)據(jù)放到輸入棧,再把數(shù)據(jù)從輸入棧放到輸出棧,此時輸出棧輸出數(shù)據(jù)的順序就和隊(duì)列一樣了,先入先出

4、代碼部分

type MyQueue struct {
	stackIn  []int // 用來保存Push數(shù)據(jù)
	stackOut []int // 用來保存Pop數(shù)據(jù)
}

// 棧構(gòu)造器
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)
	}
	// 將數(shù)據(jù)加進(jìn)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 {
	// 調(diào)用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
}

代碼可以直接拿到力扣上運(yùn)行。我已經(jīng)將細(xì)節(jié)全部用注釋解釋了,如果不懂可以私信博主。

用隊(duì)列實(shí)現(xiàn)棧

1、理論

隊(duì)列模擬棧,其實(shí)一個隊(duì)列就夠了,那么我們先說一說兩個隊(duì)列來實(shí)現(xiàn)棧的思路。

隊(duì)列是先進(jìn)先出的規(guī)則,把一個隊(duì)列中的數(shù)據(jù)導(dǎo)入另一個隊(duì)列中,數(shù)據(jù)的順序并沒有變,并沒有變成先進(jìn)后出的順序。

所以用棧實(shí)現(xiàn)隊(duì)列, 和用隊(duì)列實(shí)現(xiàn)棧的思路還是不一樣的,這取決于這兩個數(shù)據(jù)結(jié)構(gòu)的性質(zhì)。

但是依然還是要用兩個隊(duì)列來模擬棧,只不過沒有輸入和輸出的關(guān)系,而是另一個隊(duì)列完全用又來備份的!

如下面動畫所示,用兩個隊(duì)列que1和que2實(shí)現(xiàn)隊(duì)列的功能,que2其實(shí)完全就是一個備份的作用,把que1最后面的元素以外的元素都備份到que2,然后彈出最后面的元素,再把其他元素從que2導(dǎo)回que1。

模擬的隊(duì)列執(zhí)行語句如下:

queue.push(1);        
queue.push(2);        
queue.pop();   // 注意彈出的操作       
queue.push(3);        
queue.push(4);       
queue.pop();  // 注意彈出的操作    
queue.pop();    
queue.pop();    
queue.empty();

Go語言有沒有隊(duì)列和棧結(jié)構(gòu)

2、算法題

接下來看一下LeetCode原題225. 用隊(duì)列實(shí)現(xiàn)棧

請你僅使用兩個隊(duì)列實(shí)現(xiàn)一個后入先出(LIFO)的棧,并支持普通棧的全部四種操作(push、top、pop 和 empty)。

實(shí)現(xiàn) MyStack 類:

void push(int x) 將元素 x 壓入棧頂。 int pop() 移除并返回棧頂元素。 int top() 返回棧頂元素。 boolean empty() 如果棧是空的,返回 true ;否則,返回 false 。

注意:

你只能使用隊(duì)列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 這些操作。 你所使用的語言也許不支持隊(duì)列。 你可以使用 list (列表)或者 deque(雙端隊(duì)列)來模擬一個隊(duì)列 , 只要是標(biāo)準(zhǔn)的隊(duì)列操作即可。

3、思路

用兩個隊(duì)列que1和que2實(shí)現(xiàn)隊(duì)列的功能,que2其實(shí)完全就是一個備份的作用,把que1最后面的元素以外的元素都備份到que2,然后彈出最后面的元素,再把其他元素從que2導(dǎo)回que1。

4、使用兩個隊(duì)列實(shí)現(xiàn)

type MyStack struct {
    //創(chuàng)建兩個隊(duì)列
    queue1 []int
    queue2 []int
}


func Constructor() MyStack {
    return MyStack{	//初始化
        queue1:make([]int,0),
        queue2:make([]int,0),
    }
}


func (this *MyStack) Push(x int)  {
     //先將數(shù)據(jù)存在queue2中
    this.queue2 = append(this.queue2,x)	
   //將queue1中所有元素移到queue2中,再將兩個隊(duì)列進(jìn)行交換
    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()     //重復(fù)
    }
}

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
}

5、優(yōu)化

其實(shí)這道題目就是用一個隊(duì)列就夠了。

一個隊(duì)列在模擬棧彈出元素的時候只要將隊(duì)列頭部的元素(除了最后一個元素外) 重新添加到隊(duì)列尾部,此時在去彈出元素就是棧的順序了。

6、使用一個隊(duì)列實(shí)現(xiàn)

type MyStack struct {
    queue []int//創(chuàng)建一個隊(duì)列
}


/** 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{ //除了最后一個,其余的都重新添加到隊(duì)列里
        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函數(shù),彈出來的元素重新添加
    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
}

到此,關(guān)于“Go語言有沒有隊(duì)列和棧結(jié)構(gòu)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI