1. 程式人生 > 其它 >C語言資料結構棧

C語言資料結構棧

技術標籤:資料結構演算法c語言

Stack

一、順序棧及基本操作

用順序表實現棧儲存結構。棧的儲存結構操作必須遵循”先進後出的“的原則。

若用順序表即陣列a來儲存資料。

image-20210127150841505

即可用a[0],a[1],a[2],a[3]來分別取出資料,那麼我們用一個整型top,來表示索引(初始值為-1即空棧),每次增加一個數據top++;每次減少一個數據top–;可以模擬出棧的儲存結構”先進後出“的原則。

image-20210127150743080

1.順序棧-入棧

1)模擬空棧的情況,即陣列為空,top = -1。

image-20210127151251625

2)首先新增一個元素1,即入棧元素1,top++。

image-20210127151400120

3)延續2)方法入棧2,3,4。

image-20210127151520901

程式碼如下:

/*
    元素elem進棧,a為陣列,top值為當前棧的棧頂位置
*/
int push(int *a,int top,int elem){
    a[++top]=elem;
    return top;
}

2.順序棧-出棧

例如,我們需要將元素2出棧,即需要先將4元素出棧,再將3元素出棧,隨後才能使2元素出棧,在順序表模擬的棧出棧,元素並沒有摘掉,為了方便理解,先將元素摘掉。

image-20210127151800847

image-20210127151823467

程式碼如下:

/*
    資料元素出棧
*/
int pop(int *a,int top){
    if(top == -1){
        cout<<"空棧"<<endl;
        return -1;
    }
    cout<<"出棧元素:"<<a[top]<<endl;
    top--;       //每出棧一個元素棧頂-1
    return top;  //返回現在棧頂
}

3.順序棧-總結

順序棧只是模擬棧的出棧入棧過程,即”先進後出“,並不能很好的體現棧的儲存結構。

實現結果:image-20210127160701203

二、鏈棧及基本操作

鏈棧與順序棧類似,順序棧是以陣列的頭為 棧底,另一頭為棧頂;

鏈棧則是以單向鏈的頭為棧頂,鏈尾為棧底,實現棧的儲存結構,如圖;

image-20210127153122380

1)將連結串列頭部作為棧頂的一端,可以避免在實現資料”入棧“和”出棧“操作時做大量的遍歷連結串列;

2)在實現資料”入棧“操作時,需要將資料從連結串列的頭部插入;

3)在實現資料”出棧“操作時,需要刪除連結串列頭部的首元節點;

因此,鏈棧實際上就是一個只能採用頭插法插入或刪除資料的連結串列。

1.鏈棧-入棧

例如,將元素1、2、3、4依次入棧,即是用頭插法將各個元素依次插入新增到連結串列中,過程如下;

a)空棧: head NULL

b)1入棧: head 1 NULL

c)2入棧: head 2 1 NULL

d)3入棧: head 3 2 1 NULL

e)4入棧: head 4 3 2 1 NULL

程式碼如下:

/******* 創 建 鏈 表 節 點 結 構 *******/
typedef struct lineStack{
    int date;
    struct lineStack *next;
}lineStack;
/*
    鏈棧-入棧,elem為入棧元素
*/
lineStack *push(lineStack *stack,int elem){
    //建立儲存新元素的節點
    lineStack *newLine = (lineStack *)malloc(sizeof(lineStack));
    newLine->date = elem;
    //新節點與頭節點建立邏輯關係
    newLine->next = stack;
    //更新頭指標
    stack = newLine;
    //返回新棧頂
    return stack;
}

2.鏈棧-出棧

例如,我們需要將元素2出棧,那麼根據”先進後出“的原則,我們則需要先將元素4出棧,再將元素3出棧,隨後才能時元素2出棧,整個操作如下;

a)初始鏈棧: head 4 3 2 1 NULL

b)4出棧: head 3 2 1 NULL 4出

c)3出棧: head 2 1 NULL 3出

d)2出棧: head 1 NULL 2出

程式碼如下:

/*
    鏈棧-出棧,stack為棧頂
*/
lineStack *pop(lineStack *stack){
    //如果一開始就為空棧即沒有元素
    if(stack){
        //宣告一個新指標指向棧頂
        lineStack *top = stack;
        //更新頭指標
        stack = stack->next;
        cout<<"出棧元素為:"<<top->date<<endl;
        //此時判斷是否為空棧,若不是則新棧頂為
        if(stack){
            cout<<"新棧頂元素為:"<<stack->date<<endl;
        }else{
            cout<<"棧已空!"<<endl;
        }
        //釋放出棧元素節點
        free(top);
    }else{
        cout<<"棧內沒有元素"<<endl;
    }
    return stack; //返回新棧頂
}

3.鏈棧-總結

鏈棧即採用了單向連結串列的頭插法實現,嚴格遵循”先進後出“的原則。

實現結果:image-20210127160614437