1.リンクスタックの動作については、リンクリストと非常によく似ていますが、スタックの先頭でのプッシュ操作のみが可能な点が異なります。これは、リンクリストのヘッド挿入方法と同じです。 。
2.チェーンスタックを使用する理由は、シーケンシャルスタックを使用する場合、事前にメモリスペースを申請する必要があるためですが、少数の要素を格納すると、必然的にこのメモリスペースが無駄になります。チェーンスタックを使用する場合は、スタックにプッシュするときにのみメモリを適用し、要素を格納します。これにより、動的メモリの適用を実行できます。スタック上の実際の要素数に応じて、必要なスペースを申請できます。
3.チェーンスタックとシーケンシャルスタックの基本的な操作は同じです。これには、初期化、長さの検出、スタックが空かどうかの判断、スタックのプッシュ、スタックのポップ、スタックの最上位要素の取得が含まれます。
(1)最初に、スタック内の各ノードのノード値データと、次のスタックノードの隣のポインターを含む構造を定義します。
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
//定义一个结构体栈
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
}StackList;
typedef StackList *LStack;//声明一个指向这个结构体的指针类型Lstack
(2)初期化して、スタックを指すようにチェーンスタックの一番上にポインタを設定します。このポインタは何も格納しないので、最初にスタックの一番上のポインタをNULLに設定するだけです。
//初始化链栈
void Init(LStack *s)
{
(*s)=(LStack)malloc(sizeof(StackList));
(*s)->next=NULL;
}
(3)スタックが空であるかどうかを判断するには、スタックの最上位ポインタのポインタフィールドが空であるかどうかを判断するだけで済みます。nullの場合は0を返し、null以外の場合は1を返します。
//判断栈是否为空
int Empty(LStack s)
{
if(s->next==NULL)
{
return 0;//为空返回0,
}
return 1; //不为空返回1,
}
(4)スタックの長さを見つけます。つまり、スタックの一番上にある次の要素、つまり最初の要素から開始し、下にトラバースし、ポインターがnullを指すまでトラバースして、トラバーサルが完了したことを示します。 、1つがトラバースされていない場合、カウンターは1つインクリメントされます。一時的ポインター変数は1ビット戻りますp = p-> next
//求栈中的元素数量,即长度
int Printf(LStack s)
{
int count=0;
LStack p;
p=s->next;//指向第一个元素
while(p){
count++;
p=p->next;
}
return count;
}
(5)スタックをプッシュし、値xをスタックにプッシュします。もちろん、要素値xを格納するためのポインター変数を最初に宣言します。もちろん、このポインター変数を使用して物を格納するため、最初にこのポインターを使用する必要があります。変数メモリスペースmallocを適用し、それを格納します。
//入栈
void Push(LStack *s,ElemType x)
{
LStack p;//声明一个指针变量
p=(LStack)malloc(sizeof(StackList));//为这个指针变量分配空间
p->data=x; //将入站的元素值存入到这个指针的数据域
p->next=(*s)->next; //这两个步骤和顺序链表的操作相似。
(*s)->next=p;
}
(6)スタックからポップアウトするには、最初にスタックが空かどうかを判断する必要があります。空でない場合は、ポインタpがスタックの最初のノードを指し、eを使用して現在の値を記録します。スタックの最上位要素、次にスタックを何もせずに格納します。最上位ポインターのポインターフィールドは、ポインターpの次のノードを指し、ポインターpを解放できます。
//出栈
ElemType Pop(LStack *s)
{
LStack p;//声明一个结构体类型的指针变量
ElemType e;
p=(*s)->next;//指向栈中的栈顶元素
if(p==NULL)
{
return 0;
}
(*s)->next=p->next;//不为空的话就让栈顶元素变成当前栈顶p的下一个
e=p->data;//存放以下删除的栈顶元素
free(p); //释放指针
return e; //返回删除的栈顶指针的值
}
(7)スタックの最上位にある要素の値を取得するには、まずスタックが空かどうかを判断します。空でない場合は、スタックの最初のノードの値を返します。
//取栈顶元素的值
ElemType GetTop(LStack s)
{
if(Empty(s)){//如果栈顶元素不为空的话,则打印出栈顶元素
return s->next->data;
}
return 0;
}
(8)メイン関数、上記で定義された各関数、このモジュールのコードブロックを定義します。自分のニーズに応じて自分で定義できます。私が書いたものの一部のみを示します。
int main()
{
LStack s;
int x;
ElemType e;
//初始化栈
Init(&s);
//判断栈是否为空
x=Empty(s);
if(x)
{
printf("栈空\n");
}
//扫描要入站的元素
Push(&s,5);
Push(&s,4);
Push(&s,6);
Push(&s,8);
Push(&s,2);
//获取栈的长度
x=Printf(s);
printf("栈的长度为%d\n",x);
//获取当前栈的栈顶元素
e=GetTop(s);
if(e){//如果栈不为空的话输出
printf("当前栈顶元素为:%d\n",e);
}
//删除当前栈的栈顶元素
e=Pop(&s);
if(x)//如果栈不为空的话进行出栈操作
{
printf("删除的元素为:%d\n",e);
}
//获取当前的栈顶元素
e=GetTop(s);
if(e){//如果栈不为空的话输出
printf("当前栈顶元素为:%d\n",e);
}
x=Printf(s);
printf("栈的长度为%d\n",x);
return 0;
}
(9)私の場合の実行結果は次のとおりです。
概要:構造体を別の関数に渡すときに、構造体へのポインターを定義するときの記述方法がわからない人もいます。構造体の型がポインターではないことを定義する場合は、メインで構造体ポインター変数を定義する場合関数の場合、スタックを他の関数に渡すときにスタックを変更するには、ダブルポインター**を使用する必要があります。ここで最初に構造体へのポインター型を定義し、次に構造体型へのポインターを宣言するときは、 *を追加する必要があります。原則は同じです。間違いがある場合は、メッセージを残してください。より良い方法がある場合は、連絡を歓迎します。