ホームページ  >  記事  >  バックエンド開発  >  Go 言語にはキュー構造とスタック構造がありますか?

Go 言語にはキュー構造とスタック構造がありますか?

青灯夜游
青灯夜游オリジナル
2023-01-04 20:06:353985ブラウズ

Go 言語にはキューとスタックに関連するデータ構造はありませんが、スライスを使用してスタックとキューの操作を実装できます。 Go 言語は、主にアペンドとスライス (組み込みの配列型で操作) を使用してスタックとキューを実装します。スタックとキューを作成するための構文は "make([]int, 0)" で、スタックとキューにプッシュするための構文は次のとおりです。 「append(stack, 10)」、スタックをポップする構文は「v:=stack[len(stack)-1] stack = stack[:len(stack)-1]」です。

Go 言語にはキュー構造とスタック構造がありますか?

このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。

Go 言語にはスタックとキューに関連するデータ構造はありませんが、slices を使用してスタックとキューの操作を実装できます。次に、スタックとキューを実装します。基本操作 を一緒に実装し、スタックを使用してキュー を実装する 、キューを使用してスタック 操作を実装する も実装します。

スタックとキューの基本操作の実装

1. スタックの基本操作

実装には主に Go 言語が使用されますスタックとキューの追加とスライス (組み込みの配列型で操作)

//创建栈
stack := make([]int, 0)
//push压入栈
stack = append(stack, 10)
//pop弹出
v := stack[len(stack)-1]
stack = stack[:len(stack)-1]
//检查栈空
len(stack) == 0

2. 基本的なキュー操作

//创建队列
queue := make([]int, 0)
//enqueue入队
queue = append(queue, 10)
//dequeue出队
v := queue[0]
queue = queue[1:]
//检查队列为空
len(queue) == 0

スタックを使用してキューを実装する

1. 理論

##スタックを使用してキューの動作をモデル化します。スタックを 1 つだけ使用すると確実に機能しないため、スタックが 2 つ必要ですスタックは、入力スタックと出力スタックが 1 つずつあり、ここでは入力スタックと出力スタックの関係に注目してください。

以下のアニメーションは、次のキューの実行プロセスを次のようにシミュレートします。

実行ステートメント:

queue.push(1);
queue.push(2);
queue.pop(); 注意此时的输出栈的操作
queue.push(3);
queue.push(4);
queue.pop();
queue.pop();注意此时的输出栈的操作
queue.pop();
queue.empty();

データをプッシュするとき、データが入力に入力されている限り、出力スタックが空の場合は、すべてのプッシュ データをインポートし (すべてのデータがインポートされることに注意してください)、ポップ スタックからデータをポップします。出力スタックが空でない場合は、データをポップ スタックから直接ポップします。ポップスタック、それだけです。

最終的にキューが空かどうかを判断するにはどうすればよいでしょうか?プッシュとポップの両方が空の場合、シミュレートされたキューが空であることを意味します。

2. アルゴリズムの質問

元の LeetCode の質問を見てみましょう

232. スタックを使用したキューの実装

先入れ先出しキューを実装するには、スタックを 2 つだけ使用してください。キューは、一般的なキューでサポートされるすべての操作 (プッシュ、ポップ、ピーク、空) をサポートする必要があります:

MyQueue クラスを実装します:

void Push(int x) 要素 x を末尾にプッシュします。待ち行列 int Pop() はキューの先頭から要素を削除して返します。 int Peak() はキューの先頭にある要素を返します。 boolean empty() は、キューが空の場合は true を返し、そうでない場合は false を返します。 注:

標準のスタック操作のみを使用できます。つまり、先頭へのプッシュ、先頭からのピーク/ポップ、サイズ、および空の操作のみが有効です。 使用している言語はスタックをサポートしていない可能性があります。標準のスタック操作である限り、リストまたはデキュー (両端キュー) を使用してスタックをシミュレートできます。

3. アイデア

この問題を解決するには、出力スタックと入力スタックが必要です

まず、データを入力スタックに置きます。入力スタックからのデータを出力スタックに配置します このとき、出力スタックからの出力データの順序はキューの順序と同じです 先入れ先出し

#4. コード部分

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
}
コードは直接バックルに取り付けて実行できます。コメントで詳細を説明しましたが、理解できない場合は、ブロガーにプライベートメッセージを送信できます。

キューを使用してスタックを実装する

1.理論

キューはスタックをシミュレートします。実際には 1 つのキューで十分です。それではまず、2 つのキューを使用してスタックを実装するというアイデアについて話しましょう。

キューは先入れ先出しルールです。あるキュー内のデータが別のキューにインポートされても、データの順序は変更されず、先入れ後出しにもなりません。 -アウトオーダー。

したがって、スタックを使用してキューを実装するという考え方は、2 つのデータ構造の性質に応じて、キューを使用してスタックを実装することとは異なります。

しかし、スタックをシミュレートするには 2 つのキューを使用する必要がありますが、入力と出力の間には関係がなく、別のキューが完全にバックアップに使用されます。

下のアニメーションに示すように、キュー関数の実装には que1 と que2 の 2 つのキューが使用されます。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();

Go 言語にはキュー構造とスタック構造がありますか?

2. アルゴリズムの質問

問題を考えてみましょう。 LeetCode の元の質問

225 を参照してください。キューを使用してスタックを実装します

请你仅使用两个队列实现一个后入先出(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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

3、思路

用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

4、使用两个队列实现

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
}

5、优化

其实这道题目就是用一个队列就够了。

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

6、使用一个队列实现

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 言語にはキュー構造とスタック構造がありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。