1. 程式人生 > >棧、隊列

棧、隊列

特殊 輸入數據 浪費 單鏈表 () empty 循環 連接 class

棧和隊列也都是線性表,是操作受限的特殊線性表

棧 :先進後出

順序棧:假設有一個足夠大的存儲空間data,用於存儲棧中的元素,將棧中的元素依次存儲到數組中--順序存儲方式--順序棧。其中設置一個整形變量top,指示棧頂,即棧頂元素的數組下標,也可用來計數元素個數 將數組 data和top作為順序棧的數據成員。

技術分享圖片

#include <iostream>
#define MAXLEN 100
typedef int elementType;
//順序棧存儲定義
typedef struct sStack{
    elementType data[MAXLEN];//定義一個足夠大的數組
int top;//指示棧頂 }seqStack;//順序棧定義 //棧初始化 void initialStack(seqStack &s){ s.top = -1; } //判斷棧空 bool stackempty(seqStack &s) { if (s.top == -1) return true; return false; }//簡寫 return(s.top == -1); //判斷棧滿 bool stackfull(seqStack &s) { if (s.top == MAXLEN-1
) return true; return false } //取棧頂元素 bool getTop(seqStack &s,elementType &x){ if(stackempty){ return false; } else{ x = s.data[s.top]; return true; } } //入棧 bool push(seqStack &s,elementType x){ if (stackfull)
return false else{ s.top++;//增加棧頂 s.data[s.top] = x;//數據入棧 return true; } } //出棧 bool pop(seqStack &s, elementType &x){ if (stackempty){ return false } else{ x = s.data[s.top]; top--; return true; } }

順序棧特點:所有運算的時間復雜度均為O(1);通常一次性申請空間,只能按最大空間需求分配,容易造成空間浪費(可以使用鏈式棧代替順序棧)

鏈棧 采用鏈式存儲結構實現的棧,可以用單鏈表結構來表示,結點結構同單鏈表 鏈棧可以帶頭結點,也可以不帶頭結點。不帶頭節點棧頂指針top指示首元素節點,帶頭結點,棧頂指針top->next指示首元素節點

技術分享圖片

typedef int elementType;  //elementType 定義為整數類型

typedef struct lsNode
{
    elementType data;     //鏈棧結點數據域
    struct lsNode *next;  //鏈棧結點指針域
} node,*linkedStack;
//使後面使用node *top 或 linkedStack top都行

//初始化棧 不帶頭結點
void initialStack(node *&top)
{
    top=NULL;//將棧頂指針置空
}

//判定棧空
bool stackEmpty(node* top)
{
    if(top==NULL)
        return true;  //棧空,返回true
    else
        return false;   //棧不空,返回false
}

//取棧頂元素
bool getTop(node * top, elementType &x)
{
    if(top==NULL)
        return false;  //棧空,返回false
    else
    {
        x=top->data;   //取棧頂元素,用參數x返回
        return true;   //取棧頂成功,返回true
    }
}


//入棧
void push(node *& top, elementType x)
{
    node* s;
    
    s=new node;
    s->data=x;
    s->next=top;
    top=s;

}

//出棧
bool pop(node *& top, elementType &x)
{
    node* u;
    if(top==NULL)
        return false;   //棧空,返回false
    else
    {
        x=top->data;    //取棧頂元素,由變量x返回
        u=top;          //棧頂指針保存到u
        top=top->next;  //棧頂指針後移一個元素結點
        delete u;       //釋放原棧頂結點
        return true;    //出棧成功,返回true
    }
}

void destroyStack(node *& top)
{
    node *p,*u;
    p=top;
    while(p)
    {
        u=p;
        p=p->next;
        delete(u);        
    }
    top=NULL;
}

//交互循環壓入元素
void createLinkedStack(linkedStack &top)
{        
    elementType x;
    node *p;    
    cout<<"請輸入數據元素(整數,-9999退出):"<<endl;
    cout<<"x=";
    cin>>x;
    while(x!=-9999)   //非結束符,循環入棧
    {
        p=new node;
        p->data=x;

        p->next=top;
        top=p;

        cout<<"x=";
        cin>>x;
    }
}


鏈式棧特點:使用連續或不連續的存儲空間,各數據元素獨立存儲,依靠指針連接建立邏輯相鄰關系,對每個數據元素單獨申請結點空間,沒有棧滿溢出的情況,棧頂指針top唯一確定一個鏈式棧。

逆置單鏈表:

1、從原鏈表首元素節點依次取出放入新表即可 頭插法

void reverse(linkedStack & l)
{
    node *p,*s;
    p = l ->next;
    l->next = NULL;
    while(p)
    {
        s = p;
        p = p->next; //利用s中轉 
        s->next = l->next;
        l->next = s
    }

}

2、定義一個順序棧,循環每個節點指針入棧,首元素節點指針在棧底,將棧內節點依次彈出按尾插法來重建鏈表。

void reverse(linkedStack & l){
    SeqStack S;
    initialStack(S);
    node* p ;
    p = l->next;
    while(p){
        
        S.push(p);
        p = p->next;
    }
    l->next = NULL;
    while(!stackEmpty(S)){
        p = S.pop();
        l->next = p;
    }
    l->next = NULL
}

隊列 也是線性表,插入和刪除只能在一端進行。

技術分享圖片

普通隊列隨著刪除、插入的進行容易造成假溢出

循環隊列

技術分享圖片

#define MAXLEN 100
typedef int elementType;
//根據函數接收參數的不同 引用傳值還是指針傳值   用.給變量賦值  -> 指針賦值
typedef struct squeue
{
    elementType data[MAXLEN];
    int front,rear;
}seqQueue;

void initial(seqQueue * Q)
{
    Q->front = 0;
    Q->rear = 0;
}
bool isEmpty(seqQueue & Q)
{
    if (Q.front == Q.rear)
        return true;
    return false;
}
bool isFull(seqQueue & Q)
{
    if ((Q.rear+1)%MAXLEN == Q.front)
        return true;
    else 
        return false;
}
bool getFront(seqQueue &Q,elementType &x)
{
    if isEmpty(Q)
        return false;
    else:
        x = Q.data[[Q.front+1] %MAXLEN]
    }
bool enQueue(seqQueue &Q , elementType x)
{
    if (isFull(Q))
        return false;
    else
        Q.rear = (Q.rear+1)%MAXLEN;
        Q.data[Q.rear] = x;
        return true;
}
bool outQueue(seqQueue &Q, elementType &x)
{
    if (isEmpty(Q))
        return false;
    else 
        Q.front = (Q.front+1)%MAXLEN;
          x = Q.data[Q.front];
          return true;
}

隊列的應用 楊輝三角

技術分享圖片

void yanghuiTriangle(int n)
{
    seqQueue Q;
    initial(&Q)
    int s1,s2,x;
    cout << 1<<endl;
    enQueue(&Q ,1)
    for (int i = 2; i <= n; i++)
    {
        s1 = 0;
        for (int j = 1; j <= i-1; j++)
        {
            getFront(Q,s2);
            outQueue(&Q,x);
            cout << s1+s2 <<"\t";
            enQueue(&Q, s1+s2);  每次保證隊列中是上一行的元素 在遍歷隊列依次相加 得到下一行元素
            s1 = s2;        
        }
        cout << 1<<endl;
        enQueue(&Q,1);
    }
}

鏈隊列 節點結構和單鏈表相同,需要兩個指針分別指向隊頭和隊尾。

技術分享圖片

typedef int elementType;
typedef struct Node
{
    elementType data;
    struct Node *next;
}node;
typedef struct queue
{
    node *front;
    node *rear;    
}linkedQueue;
void initial(linkedQueue &Q){
    Q.front = new node;
    Q.rear = Q.front;
    Q.front->next = NULL;
}
bool isempty(linkedQueue &Q){
    if (Q.rear == Q.front)
        return true;
    else
        return false;
}
bool getFront(linkedQueue &Q,elementType &x)
{
    if (isempty(Q))
    {
        return false;/* code */
    }
    x =( (Q.front)->next)->data;
    return true;
}
void enQueue(linkedQueue &Q,elementType x)
{
    node* p = new node;
    p->data = x;
    p->next = NULL;
    Q.rear ->next =  p;
    Q.rear = p;
}
bool outQueue(linkedQueue &Q,elementType &x)
{
    if (isempty(Q))
    {
        return false;/* code */
    }
    node *p = new node;
    p = Q.front->next;
    x = p->data;
    Q.front->next = p->next;
    delete(p);
    if (Q.front->next == NULL )//只有一個節點時
        Q.rear = Q.front;
    return true
}
void destory(linkedQueue &Q){
    node *p,*u;
    p = Q.front;
    while(p){
        u = p;
        p = p->next;
        delete(u);
    }
    Q.front = NULL;
    Q.rear =NULL;
}

棧、隊列