研究ノート:ビッグトークデータ構造-スタック

ビッグトークのデータ構造-スタック

スタックの定義

スタックは、テーブルの最後にのみ挿入および削除する線形テーブルです。挿入と削除が可能な一方の端はスタックの最上位と呼ばれ、もう一方の端はスタックの最下部と呼ばれます。

  • スタックは後入れ先出し線形テーブルとも呼ばれ、LIFO構造と呼ばれます
  • スタックの挿入操作はスタックへのプッシュとプッシュであり、スタックの削除操作はポップです。
typedef int SElemType; /*SElemType类型根据实际情况而定,这里假设为int*/
typedef struct
{
    
    
    SElemType data[MAXSIZE];
    int top; /*空栈top=-1,栈满etc*/
}SqStack;

スタックのシーケンシャルストレージ構造

/*进栈操作 插入元素e为新的栈顶元素*/
Status Push(SqStack *S,SElemType e)
{
    
    
    if(S->top == MAXSIZE -1) /*栈满*/
    {
    
    
        return ERROR;
    }
    S->top++; /*栈顶指针增加一*/
    S->data[S->top] = e; /*将新插入元素赋值给栈顶空间*/
    return OK;
}
/*出栈操作:若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqStack *S,SElemType *e)
{
    
    
    if(S->top == -1)
        return ERROR;
    *e=S->data[S->top]; /*将要删除的栈顶元素赋值给e*/
    S->top--; /*栈顶指针减一*/
    return OK;
}

2スタック共有スペース-配列を使用して2つのスタックを格納します

  1. 同じタイプのスタックの設計手法
  2. top1 + 1 == top2(スタックがいっぱい);スタック1は空のスタック、top2 = 0、スタック2がいっぱい、スタック2は空のスタック、スタック1のtop1はn-1、スタック1はいっぱいです。
/*两栈共享空间结构*/
typedef struct
{
    
    
    SElemType data[MAXSIZE];
    int top1; /*栈1栈顶指针*/
    int top2; /*栈2栈顶指针*/
}SqDoubleStack;

Status Push(SqDoubleStack *S,SElemType e, int stacklNumber)
{
    
    
    if(S->top1+1==S->top2) /*栈满*/
        return ERROR;
/* ****自增、自减
* ++i/--i, i自增/减1后再参与其他的运算;i++/i--,i参与运算后,i的值域再自增/减1*/
    if(stacklNumber==1)  /*若栈1有元素进栈*/
        S->data[++S->top1] = e; /*若栈1给top1+1后给数组元素赋值*/
    else if (stacklNumber ==2)/*若栈2有元素进栈*/
        S->data[--S->top2]=e; /*若栈2给top2-1后给数组元素赋值*/
    return OK;
}
/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqDoubleStack *S,SElemType *e, int stackNumber)
{
    
    
    if (stackNumber == 1) {
    
    
        if (S->top1 == -1)  /*空栈,溢出*/
            return ERROR;
        *e = S->data[S->top1--]; /*栈1的栈顶元素出栈*/
    }
    if (stackNumber == 2)
    {
    
    
        if(S->top2==MAXSIZE)  /*空栈,溢出*/
            return ERROR;
        *e = S->data[S->top2++]; /*栈2的栈顶元素出栈*/
//        data[s--]等价于data[s];s--;
//        data[++s]等价于++s;data[s];
//        data[++s],++s入栈;先取出data[s],s--会删除栈顶的元素
    }
}

チェーンストレージ構造とスタックの実装

  1. 単一リンクリストにはヘッドポインタがあり、スタックのトップポインタも必要なので、スタックの最上位を単一リンクリストの先頭に配置します(ヘッドノード->スタックトップ)。
  2. スタックがいっぱいの場合、チェーンスタックは基本的に存在しません。空のスタックの場合、リンクリストは元々、空を指すヘッドポインターを定義しており、チェーンスタックの空はtop = NULLです。
typedef struct StackNode
{
    
    
    ElemType data;
    struct StackNode *next;
}StackNode, *LinkStackPtr;

typedef struct LinkStack
{
    
    
    LinkStackPtr top;
    int count
}LinkStack;
/*
进栈操作:单链表有头指针,而栈顶指针也是必须的,因此把栈顶放在单链表的头部(头结点->栈顶):相当于头插法;插入新元素e为新的栈顶元素
 */
Status Push(LinkStack *S,SElemType e)
{
    
    
    LinkStackPtr s=(LinkStackPtr) malloc(sizeof(StackNode)); /*声明新结点*/
    s->data = e;
    s->next = S->top;  /*把当前的栈顶元素赋值给新结点的直接后继*/
    S->top = s;  /*将新的结点s赋值给栈顶指针*/
    S->count++;
    return OK;
}
/*出栈操作:用p存储被删除的栈顶结点,将栈顶指针下移一位,最后释放p*/
#include <stdbool.h>
bool StackEmpty(LinkStack S)
{
    
    
    if(S.top ==NULL) /*如果是空栈,则top为*/
        return TRUE;
}
Status Pop(LinkStack *S,SElemType *e)
{
    
    
    LinkStackPtr p;
    if (StackEmpty(*S))
        return ERROR;
    *e = S->top->data;
    p = S->top;
    S->top = S->top->next;
    free(p);
    S->count--;
    return OK;
}

スタックアプリケーション

  1. 再帰、つまり自分自身を直接呼び出す関数、または一連の呼び出しステートメントを介して間接的に自分自身を呼び出す関数は、再帰関数と呼ばれ
    ます。呼び出しが行われたときに出口を満たさない条件付きコマンドの定義に注意してください。ステージ、再帰の各レイヤーについて、関数ローカル変数、パラメーター値、およびの戻りアドレスがスタックにプッシュされます。
    b。リトリートフェーズでは、スタックの最上位にあるローカル変数、パラメーター値、および戻りアドレスがポップアップ表示され、呼び出し階層で実行された残りのコードに戻り、呼び出し状態を復元するために使用されます。
  2. 4つの正規表現が評価され
    ます。a。括弧で囲まれた式は左から右に移動し、スタックは空から要素に移動し、すべての一致が成功すると最終的に空のスタックになり
    ます。b。後置式と中置式(標準の4つの算術式) )))

キュー

キューの最大長を決定できる場合は、循環キューを使用することをお勧めします。キューの長さを見積もることができない場合は、チェーンキューを使用してください。

  1. 一方の端でのみ挿入操作を許可し、もう一方の端で削除操作を許可する線形テーブル->先入れ先出しFIFO
  2. キューは、線形テーブルのシーケンシャルストレージ構造に基づいて取得されます。キューを離れるときは、すべてを移動する必要があります。キューの要素は、配列の最初のnユニットに格納する必要があり、デキューのパフォーマンスが大幅に向上します。 。
  3. 要素が1つしかない場合、チームの頭と尾が重なってトラブルを引き起こすのを避けるために、前(頭の要素を指す)と後(尾の要素を指す)の2つのポインターを使用します
    。3.1。質問1:前(ヘッド要素を指す)、リア(キューの最後の要素を指す)が、キューの
    終わりには位置がないが、キュー先頭には位置があるという状況になります->循環キューとして記録される、キューのエンドツーエンドの順次ストレージ構造
    3.2。質問2:キューが空かどうかを判断するには、front == Rearを使用しますが、キューがいっぱいの場合も条件が満たされます
    ->方法1 :フラグ変数を設定します。フラグ= 0の場合、キューは空です。フラグ= 1の場合、キューはいっぱいです
    ->方法2:キューがいっぱいの場合、要素を保持しますスペース
    a。キューがいっぱいの状態:(rear + 1 )%QueueSize == front(後部は前部の右側または前部の左側にある場合があります)
    b。キューの長さ:(rear-front + QueueSize)

循環キューのシーケンシャルストレージ構造

typedef int QElemType; //视情况而定
typedef struct
{
    
    
    QElemType data[MAXSIZE];
    int front; /*头指针*/
    int rear; /*尾指针,若队列不空,指向队列元素的下一个位置*/
}SqQueue;

/*初始化一个空队列*/
Status InitQueue(SqQueue *Q)
{
    
    
    Q->front= 0;
    Q->rear=0;
    return OK;
}
/*返回Q的元素个数,也就是队列的当前长度*/
int QueueLength(SqQueue Q)
{
    
    
    return (Q.rear - Q.front+MAXSIZE)%MAXSIZE;
}
/*循环队列的入队列操作代码*/
Status EnQueue(SqQueue *Q,QElemType e) {
    
    
    if ((Q->rear + 1) % MAXSIZE == Q->front) /*队列满的判断*/
        return ERROR;
    Q->data[Q->rear] = e;  //将元素e赋值给队尾
    Q->rear = (Q->rear + 1) % MAXSIZE; //rear指针向后移一个位置,在末尾则转到数组头部
}

/*循环队列的出队列操作代码*/
Status DeQueue(SqQueue *Q,QElemType *e)
{
    
    
    if (Q->front == Q->rear)
        return ERROR;
    *e= Q->data[Q->front]; //将队头元素赋值给e
    Q->front=(Q->front+1)%MAXSIZE; //front指针向后移一位置,若到最后转到数组头部
}

チェーンキュー

線形テーブル、エンドインおよびエンドアウト、チェーンストレージ構造、およびキューの実現の単一リンクリスト

typedef int QElemType;
typedef struct QNode
{
    
    
    QElemType data;
    struct QNode *next;
}QNode,*QueuePtr;

typedef struct  //队列的链表结构
{
    
    
    QueuePtr front,rear; //对头、队尾指针
}LinkQueue;

/*插入元素e为Q的新的队尾元素*/
#include <math.h>
Status EnQueue(LinkQueue *Q,QElemType e)
{
    
    
    QueuePtr  s = (QueuePtr) malloc(sizeof(QNode));
    if (!s)  //存储分配失败
        exit(OVERFLOW);
    s->data=e;
    s->next=NULL;
    Q->rear->next=s; //把拥有yuansue新结点s赋值为原队尾结点的后继
    Q->rear=s; //把当前的s设置为队尾结点,rear指向s
    return OK;
}
Status DeQueue(LinkQueue *Q,QElemType *e)
{
    
    
    QueuePtr p;
    if (Q->front == Q->rear)
        return ERROR;
    p= Q->front->next; //将要删除的队头结点暂存给p
    *e = p->data; // 将要删除的队头结点的值赋值给*e
    Q->front->next = p->next; //将原队头结点后继赋值给头结点后继
    if (Q->rear == p)
        Q->rear = Q->front; //若队头是队尾,则删除后将rear指向头结点(只有头结点和一个元素)
    free(p);
    return OK;
}

おすすめ

転載: blog.csdn.net/weixin_43464554/article/details/113264820