ホームページ  >  記事  >  バックエンド開発  >  Go言語のスタックとヒープとは何ですか?

Go言語のスタックとヒープとは何ですか?

青灯夜游
青灯夜游オリジナル
2023-01-03 10:35:044107ブラウズ

スタックはデータ構造であり、実行スレッド用に予約されたメモリ空間です。スタックでは線形テーブルの一端にのみデータを入れることができ、データはこの端から取り出されます。つまり、先入れ後出し、後入れ先出しに従って、削除される順序でスタックから要素を削除します。ヒープは、動的割り当て用に予約されたメモリ領域であるデータ構造です。スタックとは異なり、ヒープからのブロックの割り当てと再割り当てに固定パターンはなく、いつでも割り当てと解放ができます。

Go言語のスタックとヒープとは何ですか?

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

Go 言語におけるスタックとヒープ

プログラミング言語には、ヒープとスタックという 2 つの非常に重要な概念があります。

ヒープとスタックは 2 つの非常に重要なデータです。構造はよく使用されます。プログラムを編集するとき、Go 言語も例外ではありません。

これら 2 つのデータ構造を見てみましょう。

スタック

スタックでは、線形テーブルの一方の端にのみデータを入れることができ、データはこの端で取り出されます。 end、つまり、先入れ後出しに従って、後入れ先出しの順序でスタックから要素を削除します。

要素をスタックに入れるプロセスはプッシュと呼ばれます。スタックにプッシュすると、スタック上の要素の数が増加します。スタックに最後に置かれた要素はスタックの一番上にあり、スタックに最初に置かれた要素はスタックの一番下にあります。

スタックから要素を取り出す場合、スタックの先頭からのみ取り出すことができます。要素を取り出すとスタックの番号は小さくなり、最初に入れられた要素が常に取り出されます。最後に入れられた要素が常に取り出されます。最初に取り出されます。

Go言語のスタックとヒープとは何ですか?

スタックの使用をシミュレートするために配列をよく使用します:

スタックのプッシュとポップの実装コードは次のとおりです:

package main
import (
   "fmt"
   "errors"
)

//使用数组来模拟一个栈的使用
type Stack struct {

   MaxTop int       // 表示我们栈最大可以存放数个数
   Top int          // 表示栈顶, 因为栈顶固定,因此我们直接使用Top
   arr [5]int       // 用一个数组模拟栈
}

//入栈函数
func (this *Stack) Push(val int) (err error) {

   //先判断栈是否满了
   if this.Top == this.MaxTop - 1 {
      fmt.Println("stack full")
      return errors.New("stack full")
   }
   this.Top++
   //放入数据
   this.arr[this.Top] = val
   return
}

//出栈函数
func (this *Stack) Pop() (val int, err error) {
   //判断栈是否空
   if this.Top == -1 {
      fmt.Println("stack empty!")
      return 0, errors.New("stack empty")
   }

   //先取值,再 this.Top--
   val =  this.arr[this.Top]
   this.Top--
   return val, nil
}

//遍历栈,注意需要从栈顶开始遍历
func (this *Stack) List() {
   //先判断栈是否为空
   if this.Top == -1 {
      fmt.Println("stack empty")
      return
   }
   fmt.Println("栈的情况如下:")
   for i := this.Top; i >= 0; i-- {
      fmt.Printf("arr[%d]=%d\n", i, this.arr[i])
   }
}

func main() {

   stack := &Stack{
      MaxTop : 5,    // 表示最多存放5个数到栈中
      Top : -1,      // 当栈顶为-1,表示栈为空
   }

   //入栈
   stack.Push(1)
   stack.Push(2)
   stack.Push(3)
   stack.Push(4)
   stack.Push(5)
   stack.List()//显示

   //出栈
   val, _ := stack.Pop()
   fmt.Println("出栈val=", val)    // 5
   stack.List()                    //显示
}

ヒープ

メモリ割り当てにおけるヒープは、部屋にさまざまな家具を配置するのと似ており、家具のサイズは大きくても小さくてもかまいません。家具を見つける必要があるので、家具が収まる十分な広さのスペースに家具を置きます。

家具を置いたり置いたりを繰り返すと、部屋の中の空間が乱雑になってしまいますが、この空間に家具を置くと、十分なスペースがあるのに、それぞれの空間がバラバラになってしまいます。 、家具を置くための連続したスペースがありません。現時点では、メモリ アロケータはこれらのスペースを調整して最適化する必要があります。

Go言語のスタックとヒープとは何ですか?

ヒープ割り当てメモリやスタック割り当てメモリと比較して、ヒープは予測できないサイズのメモリ割り当てに適しています。

ヒープとスタックの割り当て

変数定義が完了すると、通常はヒープとスタック領域に割り当てられます。それはどの空間に存在しますか? それは、メモリの動的割り当て (new/malloc) があるかどうかによって異なります。

たとえば、次のケースです。

ケース 1

var p *int    //全局指针变量
func f(){
    var i int
    i = 1
    p = &i    //全局指针变量指向局部变量i
}

ケース 2

func f(){
    p := new(int) //局部指针变量,使用new申请的空间
    *p = 1
}

最初のケースでは、var を使用してローカル変数を定義していますが、 i の割り当てによる グローバル ポインタ変数 p を指定すると、関数が終了しても i はこの時点では解放されないため、ローカル変数 i がヒープに適用されます (プログラマが手動で解放します)。

  • ローカル変数: 関数で定義された変数。動的なライフサイクルがあります。実行されるたびに新しいエンティティが作成され、誰も使用しなくなるまで存続します (たとえば、外部ポインター それを指します。関数が終了するときにこの変数にアクセスするパスはありません) この時点で、それが占有するスペースはリサイクルされます

2 番目のケースでは、new を使用してスペースを適用します、関数を終了すると p が失われるため、関数が解放されるため、p はスタックに適用されます (自動的に解放されます)

[関連する推奨事項: Go ビデオ チュートリアル プログラミング教育]

以上がGo言語のスタックとヒープとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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