システムプログラマー成長計画-組合せの威力(三)
3180 ワード
転載の際は出典と作者の連絡先を明記してください
文章の出所:http://www.limodev.cn/blog 作者の連絡先:李先静
スタック
スタックは後進先出(LIFO,last in first out)のデータ構造であり,キューの先進先出(FIFO)に比べてこの規則はあまり公平ではないようで,コンピュータはこれにかかわらない.実際、スタックは最も重要なデータ構造の一つです.スタックがなく、プッシュダウンオートマチックベースのコンパイラが動作せず、アセンブリを書くしかありません.スタックがなく、再帰/マルチレベル関数呼び出しが実現できず、プログラムが動作しません.
スタックの主なインタフェース関数は次のとおりです.
oスタックスタックを作成する_create oスタックトップ要素stack_top oはスタックトップstack_に要素を入れますpush oスタックトップ要素stack_pop o取スタック内の要素個数stack_length oスタック内の要素stack_を巡るforeach oスタックを破棄stack_destroy
スタックはチェーンテーブルと配列の特殊な形式です.次に、チェーンテーブルを再利用してスタックを実現します.
oスタックのデータ構造
oスタックの作成
oスタックトップ要素を取る
o要素をスタックトップに入れる
oスタックトップ要素の削除
oスタック内の要素の数を取る
oスタック内の要素を巡る
oスタックの破棄
スタックは非常に重要なデータですが、不思議なことに私たちはそれを書く機会が少ないです.実際、私は仕事の中でスタックを書いたことがありません.これはどういうことですか.なぜなら、私たちのコンピュータ自体はスタックに基づいているので、多くのことはコンピュータが私たちが知らないうちに処理してくれました.例えば、関数呼び出し(特に再帰呼び出し)、コンピュータが処理してくれました.再帰的降下による構文解析は,関数呼び出しの再帰性を利用し,明示的な構造スタックも必要としない.
文章の出所:http://www.limodev.cn/blog 作者の連絡先:李先静
スタック
スタックは後進先出(LIFO,last in first out)のデータ構造であり,キューの先進先出(FIFO)に比べてこの規則はあまり公平ではないようで,コンピュータはこれにかかわらない.実際、スタックは最も重要なデータ構造の一つです.スタックがなく、プッシュダウンオートマチックベースのコンパイラが動作せず、アセンブリを書くしかありません.スタックがなく、再帰/マルチレベル関数呼び出しが実現できず、プログラムが動作しません.
スタックの主なインタフェース関数は次のとおりです.
oスタックスタックを作成する_create oスタックトップ要素stack_top oはスタックトップstack_に要素を入れますpush oスタックトップ要素stack_pop o取スタック内の要素個数stack_length oスタック内の要素stack_を巡るforeach oスタックを破棄stack_destroy
スタックはチェーンテーブルと配列の特殊な形式です.次に、チェーンテーブルを再利用してスタックを実現します.
oスタックのデータ構造
struct _Stack
{
DList* dlist;
};
ここではキューのデータ構造と同様に、チェーンテーブルで構成されています.oスタックの作成
Stack* stack_create(DataDestroyFunc data_destroy, void* ctx)
{
Stack* thiz = (Stack*)malloc(sizeof(Stack));
if(thiz != NULL)
{
if((thiz->dlist = dlist_create(data_destroy, ctx)) == NULL)
{
free(thiz);
thiz = NULL;
}
}
return thiz;
}
スタックを作成するときは、自分のスペースを割り当てる以外に、双方向チェーンテーブルを簡単に作成します.oスタックトップ要素を取る
Ret stack_top(Stack* thiz, void** data)
{
return_val_if_fail(thiz != NULL && data != NULL, RET_INVALID_PARAMS);
return dlist_get_by_index(thiz->dlist, 0, data);
}
チェーンテーブルの最初の要素はスタックトップであり,スタックトップの要素はチェーンテーブルの最初の要素であると考えられる.o要素をスタックトップに入れる
Ret stack_push(Stack* thiz, void* data)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
return dlist_prepend(thiz->dlist, data);
}
エレメントをスタックの上部に挿入すると、エレメントをチェーンヘッダーに挿入します.oスタックトップ要素の削除
Ret stack_pop(Stack* thiz)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
return dlist_delete(thiz->dlist, 0);
}
スタックトップ要素の削除は、チェーンテーブルを削除する最初の要素です.oスタック内の要素の数を取る
size_t stack_length(Stack* thiz)
{
return_val_if_fail(thiz != NULL, 0);
return dlist_length(thiz->dlist);
}
スタック内の個数はチェーンテーブルの個数に等しい.oスタック内の要素を巡る
Ret stack_foreach(Stack* thiz, DataVisitFunc visit, void* ctx)
{
return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);
return dlist_foreach(thiz->dlist, visit, ctx);
}
ループスタック内の要素は、ループチェーンテーブル内の要素と同じです.oスタックの破棄
void stack_destroy(Stack* thiz)
{
if(thiz != NULL)
{
dlist_destroy(thiz->dlist);
thiz->dlist = NULL;
free(thiz);
}
return;
}
双方向チェーンテーブルを破棄し、独自のスペースを解放します.スタックは非常に重要なデータですが、不思議なことに私たちはそれを書く機会が少ないです.実際、私は仕事の中でスタックを書いたことがありません.これはどういうことですか.なぜなら、私たちのコンピュータ自体はスタックに基づいているので、多くのことはコンピュータが私たちが知らないうちに処理してくれました.例えば、関数呼び出し(特に再帰呼び出し)、コンピュータが処理してくれました.再帰的降下による構文解析は,関数呼び出しの再帰性を利用し,明示的な構造スタックも必要としない.