データ構造 - スタックの実装(動的拡張バージョン)

ここに画像の説明を挿入

スタック(stack) は、スタックまたはスタックとも呼ばれ、コンピューター サイエンスにおける抽象データ型であり、順序付けされた線形データ コレクションの一端 (スタックのトップ、トップと呼ばれる) でのみデータの追加 (プッシュ) と削除を許可します。 ). データ (ポップ) 操作。したがって、後入れ先出し (LIFO、後入れ先出し) の原則に従って動作し、スタックは通常 1 次元配列またはリンク リストによって実装されます。これは、別の順序付けされた線形データ収集キューとよく比較されます。
ここに画像の説明を挿入
ここに画像の説明を挿入

// 初始化栈
void StackInit(Stack* ps)
{
    
    
	assert(ps);
	ps->_a = (STDataType*)malloc(sizeof(STDataType)*4);
	if (ps->_a == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	ps->_capacity = 4;
	ps->_top = 0;//top是栈顶元素的下一个位置
	//ps->_top = -1;//top是栈顶元素位置
}

このコードはスタックの初期化操作を実装します。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
次に、malloc 関数を使用してスタックの初期領域を割り当てます。ここでは 4 要素の領域が割り当てられ、割り当てに失敗した場合はエラー メッセージが出力されて返されます。
次に、割り当てられた領域サイズ 4 をスタックの容量 _capacity に割り当てます。
最後に、スタックの最上位要素の次の位置を 0 に初期化します (つまり、_top = 0)。
ここでのスタック実装は配列を使用してシミュレートされており、_a は配列の最初のアドレスを指すことに注意してください。同時に、スタックの容量は動的に拡張可能であり、スタック領域が不足した場合には自動的に拡張されます。

// 入栈
void StackPush(Stack* ps, STDataType data)
{
    
    
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
    
    
		STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * ps->_capacity*2);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity *= 2;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

このコードはスタックのプッシュ操作を実装します。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
次に、スタックがいっぱいかどうか、つまり、_top が _capacity と等しいかどうかを判断します。スタックがいっぱいの場合は、拡張する必要があります。
拡張が必要な​​場合は、realloc 関数を使用して領域を再割り当てし、元の領域のサイズを 2 倍にします。割り当てに失敗した場合は、エラーメッセージを出力してリターンします。
新しく割り当てられた空間アドレスを tmp ポインタに格納し、元の空間ポインタ _a が tmp ポインタを指すようにします。
スタックの容量 _capacity を 2 倍すると、容量が 2 倍になったことを示します。
スタックにプッシュする要素データをスタックの先頭、つまり _a[_top] に格納します。
スタックトップポインタ _top に 1 を追加して、次の位置を指します。
ここでのプッシュ操作は動的に拡張するスタックを実装しており、スタックがいっぱいになると自動的に拡張されることに注意してください。同時に、プッシュ操作では要素をスタックの先頭位置に格納し、先頭ポインタ _top に 1 を加えて次の位置を指します。つまり、スタックの先頭ポインタは次の位置を指します。自由なポジション。

// 出栈
void StackPop(Stack* ps)
{
    
    
	assert(ps);
	assert(!StackEmpty(ps));
	ps->_top--;
}

このコードはスタックのポップアウト操作を実装します。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
次に、assert マクロ関数を使ってスタックが空かどうか、つまりスタックの先頭ポインタ _top が 0 かどうかを確認し、空であればプログラムを終了します。
先頭ポインタ _top を 1 減らして、スタックの先頭要素がポップされたことを示します。
ここでのポップ操作は、トップ ポインタ _top を 1 だけデクリメントするだけで、実際にスタックのトップ要素を削除するわけではないことに注意してください。スタックの最上位の要素を削除する必要がある場合は、操作の完了後に、その要素が占めていたスペースを手動で解放できます。

// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
    
    
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}

このコードはスタックの最上位要素を取得する操作を実装しており、具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
次に、assert マクロ関数を使ってスタックが空かどうか、つまりスタックの先頭ポインタ _top が 0 かどうかを確認し、空であればプログラムを終了します。
スタックの最上位要素、つまりスタックの最上位要素の値を表す _a[_top-1] を返します。
ここでのスタックの最上位要素を取得する操作は、スタックから要素をポップするのではなく、スタックの最上位要素の値を取得するだけであることに注意してください。スタックの最上位要素を削除する必要がある場合は、最初にポップ操作を呼び出してから、スタックの新しい最上位要素を取得してください。

// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top;
}

このコードは、スタック内の有効な要素の数を取得する操作を実装します。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
スタック内の有効な要素の数、つまりスタック トップ ポインター _top の値を返します。
なお、ここでいうスタックの有効要素数とは、スタックの容量ではなく、実際にスタックに格納されている要素の数である。

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top == 0;
}

このコードはスタックが空かどうかを検出する操作を実装しています。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
スタックが空かどうか、つまりスタック トップ ポインター _top が 0 かどうかを判断します。0 の場合はスタックが空であることを意味し、ゼロ以外の結果を返し、それ以外の場合は 0 を返します。
なお、ここでのスタックが空演算かどうかの検出は、スタックの先頭ポインタ_topが0かどうかを判定することで実現される。

// 销毁栈
void StackDestroy(Stack* ps)
{
    
    
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = 0;
	ps->_top = 0;
}

このコードはスタックを破棄する操作を実装しています。具体的な実装は次のとおりです。

まず、assert マクロ関数を使用して、受信スタック ポインタ ps が空かどうかを確認し、空であればプログラムを終了します。
スタック領域を解放します。つまり、free 関数を使用して、スタック内の要素によって占有されている領域を解放します。
スタック領域ポインタ _a を NULL に設定し、スタックが破棄されたことを示します。
スタック容量 _capacity を 0 に設定すると、スタック容量が空になったことを示します。
スタック トップ ポインター _top を 0 に設定し、スタックに要素がないことを示します。
ここでスタックを破棄する操作は、スタック空間を解放し、対応するメンバ変数の値を 0 または空にリセットしますが、スタック構造自体が占有している空間を解放するわけではないことに注意してください。スタックを完全に破棄する必要がある場合は、スタック構造によって占有されているスペースを手動で解放する必要があります。

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
    
    
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
// 初始化栈
void StackInit(Stack* ps)
{
    
    
	assert(ps);
	ps->_a = (STDataType*)malloc(sizeof(STDataType)*4);
	if (ps->_a == NULL)
	{
    
    
		perror("malloc fail");
		return;
	}
	ps->_capacity = 4;
	ps->_top = 0;//top是栈顶元素的下一个位置
	//ps->_top = -1;//top是栈顶元素位置
}

// 入栈
void StackPush(Stack* ps, STDataType data)
{
    
    
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
    
    
		STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * ps->_capacity*2);
		if (tmp == NULL)
		{
    
    
			perror("realloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity *= 2;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

// 出栈
void StackPop(Stack* ps)
{
    
    
	assert(ps);
	assert(!StackEmpty(ps));
	ps->_top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
    
    
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps)
{
    
    
	assert(ps);
	return ps->_top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
    
    
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = 0;
	ps->_top = 0;
}
int main()
{
    
    
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);
	while(!StackEmpty(&st))
	{
    
    
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	StackDestroy(&st);
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_51799303/article/details/131351361