【algo&ds】3.棧和隊列

1.堆棧

堆棧(Stack):具備必定操做約束的線性表(只在一端(棧頂,Top)作插入、刪除)node

  • 先進後出特性

1.1堆棧的抽象數據類型描述

類型名稱: 堆棧(Stack)
數據對象集:一個有0個或多個元素的有窮線性表。
操做集:長度爲MaxSize的堆棧S  Stack,堆棧元素item  ElementType
一、Stack CreateStack( int MaxSize ): 生成空堆棧,其最大長度爲MaxSize;
二、int IsFull( Stack S, int MaxSize ):判斷堆棧S是否已滿;
三、void Push( Stack S, ElementType item ):將元素item壓入堆棧;
四、int IsEmpty ( Stack S ):判斷堆棧S是否爲空;
五、ElementType Pop( Stack S ):刪除並返回棧頂元素;數組

Snipaste_2019-11-17_19-17-54.png

Push 和 Pop 能夠穿插交替進行;
按照操做系列
(1)Push(S,A), Push(S,B),Push((S,C),Pop(S),Pop(S),Pop(S)
堆棧輸出是?函數

CBA設計

(2) 而Push(S,A), Pop(S),Push(S,B),Push((S,C),Pop(S),Pop(S)
堆棧輸出是?3d

ACB指針

棧分爲順序棧和鏈式棧。code

1.2順序棧

棧的順序存儲結構一般由一個一維數組和一個記錄棧頂元素位置的變量組成。對象

1.順序棧定義

#define MaxSize <儲存數據元素的最大個數>
typedef struct SNode *Stack;
struct SNode {
    ElementType Data[MaxSize];
    int Top;
};

2.入棧

void Push( Stack PtrS, ElementType item ) {
    if ( PtrS->Top == MaxSize-1 ) {
        printf("堆棧滿");
        return;
    } else {
        PtrS->Data[++(PtrS->Top)] = item;
        return;
    }
}

3.出棧

ElementType Pop( Stack PtrS ) {
    if ( PtrS->Top == -1 ) {
        printf("堆棧空");
        return ERROR; /* ERROR是ElementType的特殊值,標誌錯誤 */
    } else
        return ( PtrS->Data[(PtrS->Top)--] );
}

1.3鏈式棧

棧的鏈式存儲結構實際上就是一個單鏈表,叫作鏈棧。插入和刪除操做只能在鏈棧的棧頂進行。blog

1.鏈式棧定義

typedef struct SNode *Stack;
struct SNode {
    ElementType Data;
    struct SNode *Next;
} ;

2.堆棧初始化(創建空棧)

Stack CreateStack() {
    /* 構建一個堆棧的頭結點,返回指針 */
    Stack S;
    S =(Stack)malloc(sizeof(struct SNode));
    S->Next = NULL;
    return S;
}

3.判斷堆棧是否爲空

Snipaste_2019-11-17_19-35-43.png

int IsEmpty(Stack S)
{ 
    /*判斷堆棧S是否爲空,若爲空函數返回整數1,不然返回0 */
    return ( S->Next == NULL );
}

這裏的S並非頭節點,而是指向頭節點隊列

4.入棧

void Push( ElementType item, Stack S) {
    /* 將元素item壓入堆棧S */
    struct SNode *TmpCell;
    TmpCell=(struct SNode *)malloc(sizeof(struct SNode));
    TmpCell->Element = item;
    TmpCell->Next = S->Next;
    S->Next = TmpCell;
}

5.出棧

ElementType Pop(Stack S) {
    /* 刪除並返回堆棧S的棧頂元素 */
    struct SNode *FirstCell;
    ElementType TopElem;
    if( IsEmpty( S ) ) {
        printf(「堆棧空」);
        return NULL;
    } else {
        FirstCell = S->Next;
        S->Next = FirstCell->Next;
        TopElem = FirstCell ->Element;
        free(FirstCell);
        return TopElem;
    }
}

2.隊列

隊列(Queue):具備必定操做約束的線性表

  • 插入和刪除操做:只能在一端插入,而在另外一端刪除。
  • FIFO:先進先出

2.1隊列的抽象數據類型描述

類型名稱:隊列(Queue)
數據對象集:一個有0個或多個元素的有窮線性表。
操做集:長度爲MaxSize的隊列Q  Queue,隊列元素item  ElementType
一、Queue CreatQueue( int MaxSize ):生成長度爲MaxSize的空隊列;
二、int IsFullQ( Queue Q, int MaxSize ):判斷隊列Q是否已滿;
三、void AddQ( Queue Q, ElementType item ): 將數據元素item插入隊列Q中;
四、int IsEmptyQ( Queue Q ): 判斷隊列Q是否爲空;
五、ElementType DeleteQ( Queue Q ):將隊頭數據元素從隊列中刪除並返回。

2.2順序隊列

隊列的順序存儲結構一般由一個一維數組和一個記錄隊列頭元素位置的變量front以及一個記錄隊列尾元素位置的變量rear組成。

1.順序隊列結構體定義

#define MaxSize <儲存數據元素的最大個數>
struct QNode {
    ElementType Data[ MaxSize ];
    int rear;
    int front;
};
typedef struct QNode *Queue;

順序隊列的一個劣勢就是,隨着數據的入隊列和出隊列,front和rear指針會一直向右移動,最終可能沒法再添加新的元素,可是這個時候數組其實還有不少的空間,爲了讓隊列繼續可用,就須要數據搬移。

而爲了不數據搬移,就會把順序存儲結構的隊列設計成循環隊列

循環隊列的本質就是在入隊列的時候,rear指針會回到數組的前面去。

Snipaste_2019-11-17_20-36-50.png

你也能夠把它的邏輯圖畫成這樣

undefined

隊列空:

front==rear

隊列滿:

(rear+1)%maxsize == front

2.入隊列

void AddQ( Queue PtrQ, ElementType item) {
    if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) {
        printf("隊列滿");
        return;
    }
    PtrQ->Data[PtrQ->rear] = item;
    PtrQ->rear = (PtrQ->rear+1)% MaxSize;
}

3.出隊列

ElementType DeleteQ ( Queue PtrQ ) {
    if ( PtrQ->front == PtrQ->rear ) {
        printf("隊列空");
        return ERROR;
    } else {
        ElementType x = PtrQ->Data[PtrQ->front];
        PtrQ->front = (PtrQ->front+1)% MaxSize;
        return x;
    }
}

2.3鏈式隊列

隊列的鏈式存儲結構也能夠用一個單鏈表實現。插入和刪除操做分別在鏈表的兩頭進行。

1.鏈式隊列結構體定義

Snipaste_2019-11-17_21-12-51.png

struct Node {
    ElementType Data;
    struct Node *Next;
};
struct QNode { /* 鏈隊列結構 */
    struct Node *rear; /* 指向隊尾結點 */
    struct Node *front; /* 指向隊頭結點 */
};
typedef struct QNode *Queue;
Queue PtrQ;

2.出隊列

ElementType DeleteQ ( Queue PtrQ ) {
    struct Node *FrontCell;
    ElementType FrontElem;
    if ( PtrQ->front == NULL) {
        printf("隊列空");
        return ERROR;
    }
    FrontCell = PtrQ->front;
    if ( PtrQ->front == PtrQ->rear) /* 若隊列只有一個元素 */
        PtrQ->front = PtrQ->rear = NULL; /* 刪除後隊列置爲空 */
    else
        PtrQ->front = PtrQ->front->Next;
    FrontElem = FrontCell->Data;
    free( FrontCell ); /* 釋放被刪除結點空間 */
    return FrontElem;
}

3.入隊列

void AddQ( Queue Q, ElementType x)
{
    Node *newnode =(Node*)malloc(sizeof(Node));
    newnode->Data = x;
    newnode->Next = NULL;
    if ( PtrQ->front == NULL) {
        //空隊列
        Q->front = Q ->rear = newnode;
    } else{
        Q->rear->Next = newnode;
        Q->rear = newnode;
    }   
}
相關文章
相關標籤/搜索