序文
使用"スタックはキューを実装します「」は Likou の oj 質問で、「スタック」と「キュー」を初めて使用する初心者がスタックとキューの 2 つの構造をよりよく理解するのに役立ちます。
このトピックはLeetcodeからのものです:
トピックリンク: https://leetcode.cn/problems/implement-queue-using-stacks/
難易度: 簡単
目次
1. キューのインターフェイス:
1.1 型宣言 (MyQueue):
//模拟队列类型的声明
typedef struct {
ST stackpush; //用于模拟队列的 入队操作
ST stackpop; //用于模拟队列的 出队操作
} MyQueue;
ここでは、シミュレーションキューに 2 つのスタックを使用します
①:stackpush
シミュレーションキューに入る
②:stackpop
シミュレーションキューから出る
1.2 初期化 (myQueueCreate):
キューは 2 つのスタックによって実装されているため、2 つのスタックの初期化に注目してください。
ステップ:
- 2スタックサイズのスペースを申請し、
申請が失敗した場合に判定します。 - キュー内の 2 つのスタックについては、それらのスタックを呼び出します初期化機能 (これをお見逃しなく、Niu Niu はこれを見逃してから長い間探していました)
//队列的初始化
MyQueue* myQueueCreate() {
//给队列开辟空间
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("obj malloc fail");
}
//一定要记得这里要初始化(别漏掉了哦)
InitST(&obj->stackpush);
InitST(&obj->stackpop);
return obj;
}
1.3 キューに入る (myQueuePush)
キューに入るシミュレーションの実装は非常に簡単で、データをスタックにプッシュするだけです (キューに入るシミュレーション: stackpush
)。
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
STPush(&obj->stackpush,x);
}
1.4 キューアウト (myQueuePop)
機能要件:
チームの最初の要素をデキューし、デキューされたばかりのチームの最初の要素を返します。
デキューのシミュレーションは比較的複雑です。
- 初期状態または
stackpop
(シミュレートされた)デキューするデータがキューから出て空の場合はデータが無いので、まずstackpop
データがあるかどうかを判断し、データがある場合:直接
取得しますstackpop
スタックトップ要素としてチームリーダー要素。
データなし: シミュレートされたエンキュー スタックからすべてのデータを反転します (データを反転) - 取得した
stackpop
_スタックトップ要素としてチームリーダー要素はtop
変数を使って記録します(後で実行するため)飛び出る操作します)。 - 飛び出る(キューから出てシミュレーション)、
top
変数を返します。
int myQueuePop(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列的栈)为空,则向栈(stackpush模拟入队列的栈)要数据
{
//下面循环结束的条件是不为空
while(!STEmpty(&obj->stackpush))//将数据从模拟入队列栈全部倒过来
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
STPop(&obj->stackpop);
return top;
}
1.5 キューの空判定(myQueueEmpty)
どちらのスタックにも要素がない場合、キューは空になります。
//書き込み1
bool myQueueEmpty(MyQueue* obj) {
if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
{
return true;
}
else
return false;
}
//書き込み2.
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->stackpush) && STEmpty(&obj->stackpop);
}
1.6 キューの最初の要素 (myQueuePeek) に戻ります。
stackpop
空でない場合、チームの最初の要素はstackpop
スタックになります。上エレメント。stackpop
空の場合、チームの最初の要素はstackpush
スタックです終わりしたがって、
ここにもデータを注ぐ必要があります。
int myQueuePeek(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列)为空,则向栈(stackpush模拟入队列)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出队列)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
return top;
}
(デキュー) 関数と比較すると、この関数はキューの最初の要素を返すだけであり、デキュー操作myQueuePop
を指していないため、関数の実装時に関数を再利用できます。pop
myQueuePop
myQueuePeek
int myQueuePop(MyQueue* obj) {
int top=myQueuePeek(obj);
STPop(&obj->stackpop);
return top;
}
1.7 キューの破棄 (myQueueFree):
- 2 つのスタックの初期化によって空いたスペースを解放します。
- キューによって要求されたスペースを解放します。
void myQueueFree(MyQueue* obj) {
STDestory(&obj->stackpush);
STDestory(&obj->stackpop);
free(obj);
}
次に、コード全体:
C 言語は C++ のようにライブラリを直接呼び出すことができないため、前のコードはスタックの実装です。
typedef int stacktype;
typedef struct stack//定义栈的类型
{
stacktype* data;
int top;
int capacaity;
}ST;
void InitST(ST* ps);//初始化栈
void STPush(ST* ps, stacktype x);//压栈
void STPop(ST* ps);//出栈
bool STEmpty(ST* ps);//判断是否为空栈
stacktype STTop(ST* ps);//返回栈顶元素
void STDestory(ST* ps);//栈的销毁
void InitST(ST* ps)//初始化栈
{
assert(ps);
ps->top = -1;
ps->capacaity = 4;
ps->data = (stacktype*)malloc(ps->capacaity * sizeof(stacktype));
}
void STPush(ST* ps, stacktype x)//压栈
{
assert(ps);
if (ps->top+1 == ps->capacaity)
{
ps->capacaity *= 2;
ST* tmp = (stacktype*)realloc(ps->data, ps->capacaity * sizeof(stacktype));
if(tmp == NULL)
{
printf("增容失败\n");
}
ps->data = tmp;
}
ps->top++;
ps->data[ps->top] = x;
}
void STPop(ST* ps)//出栈
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
bool STEmpty(ST* ps)//判断是否为空栈,是空返回真
{
assert(ps);
if (ps->top == -1)
{
return true;
}
return false;
}
stacktype STTop(ST* ps)//返回栈顶元素
{
assert(ps);
return ps->data[ps->top];
}
void STDestory(ST* ps)//销毁栈
{
assert(ps);
free(ps->data);
ps->data = NULL;
ps->top = -1;
ps->capacaity = 0;
}
//模拟队列类型的声明
typedef struct {
ST stackpush;
ST stackpop;
} MyQueue;
//队列的初始化
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("obj malloc fail");
}
//一定要记得这里要初始化
InitST(&obj->stackpush);
InitST(&obj->stackpop);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
STPush(&obj->stackpush,x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
STPop(&obj->stackpop);
return top;
}
bool myQueueEmpty(MyQueue* obj) {
if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
{
return true;
}
else
return false;
//return STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop);
}
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
return top;
//return STTop(&obj->stackpop);
}
void myQueueFree(MyQueue* obj) {
STDestory(&obj->stackpush);
STDestory(&obj->stackpop);
free(obj);
}
操作結果: