1. 程式人生 > 其它 >Java基本功之for迴圈

Java基本功之for迴圈

堆疊

堆疊的抽象資料型別描述

型別名稱:堆疊(Stack)

物件資料集:一個有0個或多個元素的有窮線性表

操作集:長度為MaxSize的堆疊\(S\in Stack\),堆疊元素\(item\in ElementType\)

  1. Stack CreateStack(int MaxSize):生成空堆疊,其最大長度為MaxSize;
  2. int IsFull(Stack S, int MaxSize):判斷堆疊\(S\)是否已滿;
  3. void Push(Stack S, ElementType item):將元素\(item\)壓入堆疊;
  4. int IsEmpty(Stack S):判斷堆疊\(S\)是否為空;
  5. ElementType Pop(Stack S):刪除並返回棧頂元素;

棧的順序儲存實現

棧的順序儲存結構通常由一個一維陣列和一個記錄棧頂元素位置的變數組成

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

入棧

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

出棧

ElementType Pop(Stack PrtS){
    if (PtrS->Top == -1){
        printf(" 堆疊空 ");
        return ERROR;//ERROR是ElementType的特殊值
    }
    else
        return (PtrS->Data[(PtrS->Top)--]);
}

例子

用一個數組實現兩個堆疊,要求最大地利用陣列空間,使陣列只要有空間入棧操作就可以成功

一種比較聰明的方法是使這兩個棧分別從陣列的兩頭開始向中間生長;當兩個棧的棧頂指標相遇時,表示兩個棧都滿了

#define MaxSize <儲存資料元素的最大個數>
struct DStack{
    ElementType Data[MaxSize];
    int Top1;//堆疊1的棧頂指標
    int Top2;//堆疊2的棧頂指標
}S;
S.Top1=-1;
S.Top2=MaxSize;

void Push(struct DStack *PtrS, ElementType item, int Tag){
    if (PtrS->Top2 - PtrS->Top1 == 1){//堆疊滿
        printf(" 堆疊滿 ");
        return;
    }
    if (Tag == 1)//對第一個堆疊進行操作
        PtrS->Data[++(PtrS->Top1)] = item;
    else //對第二個堆疊進行操作
        PtrS->Data[--(PtrS->Top2)] = item;
}

ElementType Pop(struct DStack *PtrS, int Tag) {//Tag作為區分兩個堆疊的標誌
    if (Tag == 1) {//對第一個堆疊操作
        if (PtrS->Top1 == -1) {//堆疊1空
            printf(" 堆疊1空 ");
            return NULL;
        } else
            return PtrS->Data[(PtrS->Top1)--];
    } else {//對第二個堆疊操作
        if (PtrS->Top2 == MaxSize) {//堆疊2空
            printf(" 堆疊2空 ");
            return NULL;
        } else
            return PtrS->Data[(PtrS->Top2)++];
    }
}

堆疊的鏈式儲存實現

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

棧頂的指標Top應該在連結串列的頭上,因為如果在尾巴上,因為是單向連結串列,刪除操作時找不到前面一個節點

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

(1)堆疊初始化(建立空棧)

(2)判斷堆疊S是否為空

Stack CreateStack(){
    Stack S;//構建一個堆疊的頭結點,返回指標
    S = (Stack)malloc(sizeof(struct SNode));
    S->Next = NULL;
    return S;
}
int IsEmpty(Stack S){
    //判斷堆疊S是否為空,若為空,函式返回整數1,否則返回0
    return (S->Next == NULL);
}

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

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 = FristCell->Data;
        free(FirstCell);
        return TopEle
    }
}

堆疊應用:表示式求值

  1. 運算數:入棧
  2. 運算子:從堆疊中彈出適當數量的運算數,計算並結果入棧;
  3. 最後,棧頂上的元素就是表示式的結果值

基本策略:將中綴表示式轉換為字尾表示式,然後求值

  1. 運算數相對順序不變
  2. 運算子號順序發生改變
    • 需要儲存“等待中”的運算子號
    • 要將當前運算子號與“等待中”的最後一個運算子號比較

中綴表示式如何轉換為字尾表示式

  1. 運算數:直接輸出
  2. 左括號:壓入堆疊
  3. 有括號:將棧頂的運算子彈出並輸出,直到遇到左括號(出棧,不輸出);
  4. 運算子:
    • 若優先順序大於棧頂運算子時,則把它壓棧;
    • 若優先順序小於等於棧頂運算子時,將棧頂運算子彈出並輸出;再比較新的棧頂運算子,直到該運算子大於棧頂運算子優先順序為止然後將該運算子壓棧;
  5. 若個物件處理完畢,則把堆疊中存留的運算子一併輸出。