データ構造のスタック(チェーンスタック)の基本的な操作

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)私の場合の実行結果は次のとおりです。

概要:構造体を別の関数に渡すときに、構造体へのポインターを定義するときの記述方法がわからない人もいます。構造体の型がポインターではないことを定義する場合は、メインで構造体ポインター変数を定義する場合関数の場合、スタックを他の関数に渡すときにスタックを変更するには、ダブルポインター**を使用する必要があります。ここで最初に構造体へのポインター型を定義し、次に構造体型へのポインターを宣言するときは、 *を追加する必要があります。原則は同じです。間違いがある場合は、メッセージを残してください。より良い方法がある場合は、連絡を歓迎します。

 

おすすめ

転載: blog.csdn.net/BaoITcore/article/details/121257979