棧和隊列的總結


棧和隊列的總結:

                                    (有時候感覺自己掌握了,棧和隊列,可是在寫的時候會遇到不同的情況,就不會處理了,因此在這里進行總結下)。

 棧:

     棧是一端受限,一段允許進行操作的線性表。我自己理解時,會將它理解成一個裝書的盒子。放書,取書,就是進行的操作。這個的特點就是,你放了一踏書,現在你想取書,你只能先把上面的書一個個取出來,即:先放的后取,后放的先取。放在棧上說,就是先進后出。

明白了棧的定義,現在要實際的實際,首先是它的邏輯結構:線性表。它是線性的。

現在是它的存儲結構:最常采用的是順序存儲和鏈式存儲(見好多書或資料都說的最常采用的是順序存儲和鏈式存儲,百度了下不常見的沒有找到)。其中順序存儲用數組,鏈式存儲用鏈表。

順序存儲:

先進行分析下:首先要分配一個足夠大的數組(這里就出現了一個問題,要是分配的空間小,就會出現溢出的情況,這是一個潛在的隱患,但是要是分配的太過大,又會出現浪費空間,這里要做好一個估計,所以呢,我還是喜歡鏈式存儲,要多少就給多少,不用擔心空間太小或浪費),現在有了這個數組,需要的還有,必須有個東西能一個控制一端不讓操作(數組的前端從下標為0開始),一端要進行增刪,這樣就可以說是具備了棧有的特點,不讓操作的叫棧底,進行操作的是棧頂

棧的定義:(用的是順序存儲)

#define Max 100;

typedef int Datetype;

typedef struct

{

   Datetype date[Max];

   Int top;   //控制棧頂

}SeqStack,*PseqStack;

完成了定義,就要進行對棧的各種操作:初始化,判空,進棧,出棧,得到棧頂元素,銷毀棧…….

初始化:

   PseqStack Init-SeqStack( )

{

   PseqStack S;

   S=(PseqStack)malloc(sizeof(SeqStack)); //頭文件要包括stdilb.h

   S->top=-1;

   return S;

}

判空:

Int IsEmpyt(PseqStack S)

{

  if(S->top==-1)

   return 1;

else

  return 0;

}

進棧:

int  Push(PseqStack S,Datetype x)

{

   If(S->top==Max-1)

     return 0;

   else

     S->top++;

     S->date[S->top]=x;

     return 1;

}

出棧:

int  Pop(PseqStack S,int *x)

{

  if(isEmpty(PseqStack S)==1)

     return 0;

   else

    {

       *x=S->date[S->top];

        S->top--;

        return 1;

}

}

int GetTopdate(PseqStack S)

{

if(isEmpty(PseqStack S)==1)

     return 0;

   else

     return S->date[s->top]

 

 

}

int Destroy(PseqStack *S)

{

  if(*S)

   { free(s);

     *S=NULL;

      return 1;

}

return 0;

}

下面來看下鏈式存儲:

   控制入棧出棧的端口,棧頂一般是鏈表的頭,第一個節點,棧底一般是最后一個節點。(可以避免順序存儲的溢出),同時節省空間,要多少,申請多少。鏈表的運用中同時要注意一旦申請了,最后要記得釋放,不然會帶來不可預計的后果。下面是鏈式存儲的一些操作。

    typedef struct Stacknode

{

int date;

struct Stacknode *next;

 

}slStacktype;

入棧:

Int push(slStacktype *top,int x)

{

   slStacktype *p;

   if((p=( slStacktype *)malloc(sizeof(slStacktype )))==NULL)  //申請節點

     return 0;

    p->date=x;

p->next=top->next;      //用的是頭插法,top始終是棧頂。

top->next =p;

return 1;

}

出棧:

int pop(slStacktype *top)

{

slStacktype *p;

  int x;

  if(top->next==NULL)

  return NULL;

p=top->next;

top->next=p->next; //刪除節點,用x記錄要刪除的元素。

x=p->date;

free(p);

return x;

 

}

對我來說,棧和隊列,其實很相似,只不過是控制的位置不同。

   隊列:是一種限定性的線性表。這樣理解比較好,學生排隊買飯。有什么特點呢?當然,你先來,就先打飯,先吃飯。抽象到隊列上說,有隊頭,隊尾,要想加入(入隊),只能從隊尾加,想走(出隊),只能從隊頭走。即:先進先出。

  和棧一樣,它常見的兩種存儲是順序存儲和鏈式存儲。

   用順序存儲時,會遇到這樣的情況,數組並沒有滿,卻入不了隊(假溢出),原因在於隊頭沒有在數組的0下標處。一般情況下,因為隊列會存在假溢出的情況,所以采用循環隊列。

  說下循環隊列的操作吧。(理解取余)

   定義:

   typedef struct

{

   int date[Max];

   int rear;   //控制隊尾

    int front;//控制隊頭

}CirQueue;

  ① 置隊空

      void InitQueue(CirQueue *Q)

      {

              Q->front=Q->rear=0;

              Q->count=0;        //計數器置0

       }

 

  ② 判隊空

       int QueueEmpty(CirQueue *Q)

       {

            return Q->count==0;    //隊列無元素為空

        }

  ③ 判隊滿

int QueueFull(CirQueue *Q)

        {

            return Q->count==Max;  //隊中元素個數等於max時隊滿

         }

  ④ 入隊

void EnQueue(CirQueuq *Q,int x)

         {

            if(QueueFull((Q))                  

                 Error("Queue overflow");      //隊滿上溢

            Q->count ++;                         //隊列元素個數加1

            Q->data[Q->rear]=x;                  //新元素插入隊尾

            Q->rear=(Q->rear+1)%Max;           //用的是循環,當滿時頭尾相差一個空間,用於區別滿和不滿。

          }

  ⑤ 出隊

DataType DeQueue(CirQueue *Q)

          {

              int temp;

              if(QueueEmpty((Q))

                   Error("Queue underflow");      //隊空下溢

              temp=Q->data[Q->front];

              Q->count--;                        //隊列元素個數減1

              Q->front=(Q->front+1)%Max;         //循環意義下的頭指針加1

              return temp;

           }

             

  ⑥取隊頭元素

DataType QueueFront(CirQueue *Q)

            {

                if(QueueEmpty(Q))

                    Error("Queue if empty.");

                return Q->data[Q->front];

            }

        鏈式存儲:

 typedef struct node

{

Datetype date;

Struct node *next;

}Qnode;

typedef struct

{

   Qnode *front;

   Qnode *rear;

}LQueue;

 LQueue  *q;

創建:

 LQueue *init_lQueue()

{

   LQueue  *q,*p;

   q=( LQueue  *)malloc(sizeof(LQueue)); //頭尾指針

   p=( LQueue  *)malloc(sizeof(LQueue)); // 鏈隊頭結點

p->next=NULL;

q->front=q->rear=p;

 return  q;

}

入隊:

void inlQueue( LQueue  *q,datetype x)

{

   Qnode *p;

   P=( LQueue  *)malloc(sizeof(LQueue)); //與鏈表的結點增加想同。

p->data=x;

p->next=NULL;

q->rear->next=p;

q->rear =q;

}

判隊空:

int isempty(LQueue  *q)

{

   if(q->front==q->rear)

    Return 0;

   else

   return 1;

}

出隊:

 int outqueue(LQueue  *q,datedef *x)

{

 Qnode *p;

   if(isempty(q))

      {

     Printf(“隊空”);

     Return 0;

}

else

{

  P=q->front->next;     //與鏈表的刪除相同。

   q->front->next=p->next;

*x=p->date;

free(p);

if(q->front->next==NULL)

q->rear=q->front;

return turn;

}

   }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                                              By:暖暖

                                        2014.11.19


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM