1. 程式人生 > >棧(順序棧,鏈棧)

棧(順序棧,鏈棧)

順序棧

順序棧是指利用順序儲存結構實現的棧,即利用一組地址連續的儲存單元依次存放自棧底到棧頂的資料元素。

程式碼實現如下:

#include <iostream>
#include <stdio.h>
#include <malloc.h>
using namespace std;

typedef int SElemType;
typedef int Status;
#define INIT_SIZE 100
#define STACKINCREMENT 10
#define Ok 1
#define Error 0
#define True 1
#define False 0
typedef struct
{
    SElemType *base;///棧底指標
    SElemType *top;///棧頂指標
    int stacksize;///棧可用的最大容量
}SqStack;

Status InitStack(SqStack *s)///初始化棧
{
    s->base = (SElemType *)malloc(INIT_SIZE * sizeof(SElemType));///將順序棧動態分配一個最大容量為INIT_SIZE的陣列空間
    if(!s->base)///儲存分配失敗
    {
        puts("儲存空間分配失敗!");
        return Error;
    }
    s->top = s->base;///top初始為base,空棧
    s->stacksize = INIT_SIZE;///stacksize置為棧的最大容量為INIT_SIZE
    return Ok;
}
///if(base==NULL) 棧結構不存在
///棧非空時,top指向棧頂元素的上一位置

Status Push(SqStack *s, SElemType e)///壓棧(插入元素e為新的棧頂元素)
{
    if(s->top - s->base >= s->stacksize)///棧滿
    {
        s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREMENT) * sizeof(SElemType));///改變棧的記憶體大小
        if(!s->base)
        {
          puts("儲存空間分配失敗!");
          return Error;
        }
        s->top = s->base + s->stacksize;///修改棧頂位置
        s->stacksize += STACKINCREMENT;///修改棧長度
    }
    *s->top++ = e;
    return Ok;
}

Status Pop(SqStack *s, SElemType *e)///彈棧
{///刪除棧頂元素,用e返回其值
    if(s->top == s->base) return Error;///棧空時,無法進行操作
    --s->top;///棧頂指標減1
    *e = *(s->top);///將棧頂元素賦給e
    return Ok;
}

Status GetTop(SqStack *s, SElemType &e)///獲得棧頂元素
{
  if(s->top == s->base) return Error;///棧底指標和棧頂指標相同時,棧為空
  e = *(s->top - 1);///棧非空時,top始終指向棧頂元素的上一個位置
  return Ok;
}

Status visit(SElemType c)
{
    printf("%d ",c);
    return Ok;
}
Status StackTraverse(SqStack *s,Status(*visit)(SElemType))///遍歷棧
{
    SElemType *b = s->base;///此處不能直接用base或top移動,即不能改變原棧的結構
    SElemType *t = s->top;
    while(t > b)
    {
        visit(*b++);
    }
    printf("\n");
    return Ok;
}

Status ClearStack(SqStack *s)///清空棧
{
    s->top = s->base;
    return Ok;
}

Status StackEmpty(SqStack *s)///棧是否為空
{
    if(s->top == s->base) return True;///棧底指標和棧頂指標相同時,棧為空
    else  return False;
}

Status Destroy(SqStack *s)///銷燬棧
{
    free(s->base);
    s->base = NULL;
    s->top = NULL;
    s->stacksize = 0;
    return Ok;
}

int main()
{
    cout<< "1. 進棧" << endl;
    cout<< "2. 出棧" << endl;
    cout<< "3. 取棧頂元素" << endl;
    cout<< "4. 遍歷棧" << endl;
    cout<< "0. 退出" << endl << endl;
    SqStack a;///定義一個棧,命名為a
    SqStack *s = &a;///s為棧的指標
    SElemType e;
    InitStack(s);
    int n;
    puts("請輸入要進棧的個數:");
    scanf("%d", &n);
    while(n--)
    {
        int m;
        scanf("%d", &m);
        Push(s, m);
    }
    int choose = -1;
    while(choose != 0)
    {
        cout<< "請選擇:";
        cin>> choose;
        switch(choose)
        {
            case 1:
            {
                cin>> e;
                Push(s,e);
            }
            break;
            case 2:
            {
                if(StackEmpty(s))
                {
                    printf("該棧以空,無法進行該操作\n");
                    return 0;
                }
                Pop(s, &e);
                printf("出棧的元素是:%d\n", e);
                printf("元素出棧後事實上並沒有清除,依然存在於記憶體空間,所謂的出棧只是指標移動,出棧的元素是%d\n\n", *s->top);
                //判斷出棧後元素是否還存在於記憶體中
            }
            break;
            case 3:
            {
                if(StackEmpty(s))
                {
                    printf("該棧以空,無法進行該操作\n");
                    return 0;
                }
                GetTop(s, e);
                printf("棧頂元素為:%d\n\n",e);
            }
            break;
            case 4:
            {
                StackTraverse(s, visit);///遍歷該棧
                puts("");
            }
            break;
        }
    }
    Destroy(s);
    return 0;
}

程式執行: 

鏈棧

鏈棧是指採用鏈式儲存結構實現的棧,通常用單鏈表來表示。

程式碼實現如下:

#include <bits/stdc++.h>
using namespace std;
#define OK 1
#define ERROR 0
typedef long long ll;
typedef unsigned long long ull;
typedef int SElemType;
typedef int Status;
typedef struct StackNode///鏈棧的儲存結構
{
    SElemType data;
    struct StackNode *next;
}StackNode, *LinkStack;

Status InitStack(LinkStack &S)///鏈棧的初始化
{///構建一個空棧S,棧頂指標置空
    S = NULL;///鏈棧的初始化操作就是構造一個空棧,因為沒必要設頭結點,所以直接將棧頂指標置空。
    return OK;
}
Status Push(LinkStack &S, SElemType e)
{///在棧頂插入元素(將元素插入到首元結點)
    LinkStack p;
    p = new StackNode; ///生成新結點
    p->data = e;       ///將新結點指標插入棧頂
    p->next = S;       ///將新結點資料域插入棧頂
    S = p;             ///修改棧頂指標為p
    return OK;
}
Status Pop(LinkStack &S, SElemType &e)
{///刪除棧頂元素,用e返回其值
    LinkStack p;
    if(S==NULL) return ERROR;///棧空
    e = S->data;    ///將棧頂元素賦給e
    p = S;          ///用p臨時儲存棧頂元素空間
    S = S->next;    ///修改棧頂指標
    delete p;       ///釋放原棧頂元素的空間
    return OK;
}
Status GetTop(LinkStack S, SElemType &e)///取棧頂元素
{
    if(S==NULL) return ERROR;///棧空
    e = S->data;
    return OK;
}
Status StackTraverse(LinkStack S)
{
    LinkStack p;
    if(S==NULL) return ERROR;
    p = S;
    while(p)
    {
        cout<< p->data << " ";
        p = p->next;
    }
    cout<< endl;
    return OK;
}
int main()
{
    cout<< "1. 進棧" << endl;
    cout<< "2. 出棧" << endl;
    cout<< "3. 取棧頂元素" << endl;
    cout<< "4. 遍歷棧" << endl;
    cout<< "0. 退出" << endl << endl;
    LinkStack S;///定義一個棧,命名為a
    SElemType e;
    InitStack(S);
    int n, m;
    puts("請輸入要進棧的個數:");
    scanf("%d", &n);
    while(n--)
    {
        int m;
        scanf("%d", &m);
        Push(S, m);
    }
    int choose = -1;
    while(choose != 0)
    {
        cout<< "請選擇:";
        cin>> choose;
        switch(choose)
        {
            case 1:
            {
                cin>> e;
                Push(S,e);
            }
            break;
            case 2:
            {
                if(S==NULL)
                {
                    printf("該棧以空,無法進行該操作\n");
                    return 0;
                }
                Pop(S,e);
                printf("出棧的元素是:%d\n", e);
                printf("元素出棧後已經釋放空間,出棧的元素是%d\n\n", e);
            }
            break;
            case 3:
            {
                if(S==NULL)
                {
                    printf("該棧以空,無法進行該操作\n");
                    return 0;
                }
                GetTop(S, e);
                printf("棧頂元素為:%d\n\n",e);
            }
            break;
            case 4:
            {
                StackTraverse(S);///遍歷該棧
                puts("");
            }
            break;
        }
    }
    return 0;
}