数据结构——顺序栈和链栈

1.顺序栈未简化的版本

(1)顺序栈的表示

typedef struct {
    int* base;//栈底指针
    int* top;//栈顶指针
    int stacksize;//栈容量
}SqStack;

(2)顺序栈的初始化

int InitStack(SqStack& s) {
    s.base = new int[MaxSize];//给栈分配空间
    if (!s.base)  exit(OVERFLOW);
    s.top = s.base;
    s.stacksize = MaxSize;//修改栈容量
    return 1;
}

给栈分配空间,栈底指针指向数组首位的地址。

(3)判断顺序栈是否为空

int StackEmpty(SqStack s) {
    if (s.top == s.base)
        return 1;
    else
        return 0;
}

如果栈顶指针和栈底指针相同(指向同一位置),那么顺序栈就是空的。

(4)求顺序栈的长度

int StackLength(SqStack s) {
    return s.top - s.base;
}

栈顶指针与栈底指针相减就是栈内元素的个数,即长度。

(5)清空顺序栈

int ClearStack(SqStack s) {
    if (s.base) 
        s.top = s.base;
    return 1;
}

如果栈底指针不为空的话,让栈顶指针等于栈底指针即可。

(6)销毁顺序栈

int DestoryStack(SqStack& s) {
    if (s.base) {
        delete s.base;
        s.stacksize = 0;
        s.base = s.top = NULL;
    }
    return 1;
}

删除栈底指针,把栈容量改为0,然后栈底指针和栈顶指针都为NULL。

(7)顺序栈的入栈

int Push(SqStack& s, int e)
{
    if (s.top - s.base == s.stacksize)
        return 0;
    *s.top = e;
    s.top++;
    return 1;
}

如果栈满则报错,如果不满的话让栈顶指针指向的内容修改为e,栈顶指针向上移动。

(8)顺序栈的出栈

int Pop(SqStack& s, int& e)
{
    if (s.top == s.base)
        return 0;
    --s.top;
    e = *s.top;
    return 1;
}

如果栈满则报错。栈不满,栈顶指针向下移动,用e保存出栈的数据。

示例:

int main() {
    SqStack s;
    InitStack(s);
    for (int i = 0; i < 5; i++)
    {
        Push(s, i + 1);
        printf("增加%d个元素,当前栈的长度为:%d\n", i + 1,StackLength(s));
    }
    cout << endl;
    int e;
    for (int i = 0; i < 4; i++)
    {
        Pop(s, e);
        printf("弹出%d个元素,当前栈的长度为:%d\n", i + 1, StackLength(s));
    }
    return 0;
}

2.顺序栈简化版本

(1)顺序栈的表示

typedef struct SqStack{
    int data[MaxSize];
    int top=-1;
}SqStack;

       直接在结构体里面分配看空间,也就是不需要初始化了。同时也不需要栈底指针,栈顶指针初始化为-1(元素的序号从0开始)。

       顺序栈为空栈——top==-1

       顺序栈为满栈——top==MaxSize-1

(2)顺序栈的入栈

int Push(SqStack& s, int e) {
    if (s.top == MaxSize - 1) {
        return 0;
    }
    s.top++;
    s.data[s.top] = e;
    return 1;
}

 s.top向上移动后就代表了元素的索引。

(3)顺序栈的出栈

int Pop(SqStack& s, int& e)
{
    if (s.top == -1)
        return 0;
    e = s.data[s.top];
    s.top--;
}

s.top起索引作用。

示例:

int main() {
    SqStack s;
    for (int i = 0; i < 5; i++)
    {
        Push(s, i + 1);
        printf("增加%d个元素,当前栈的长度为:%d\n", i + 1,s.top+1);
    }
    cout << endl;
    int e;
    for (int i = 0; i < 4; i++)
    {
        Pop(s, e);
        printf("弹出%d个元素,当前栈的长度为:%d\n", i + 1, s.top+1);
    }
    return 0;
}

 3.链栈

(1)链栈结点定义

typedef struct StackNode {
    int data;
    struct StackNode* next;
}StackNode,*LinkStackPtr;//栈结点和指针的定义

链栈结点和链栈指针定义方式相同(类似int 和 int*的关系),结点有数据域和指针域。

(2)链栈的定义

typedef struct LinkStack {
    LinkStackPtr top;//栈顶指针
    int count;//记录元素个数
}LinkStack;//栈的定义

链栈里有一个栈顶指针,还有一个计数器。

(3)链栈的初始化

int InitStack(LinkStack& s) {
    //s.top=new StackNode;
    s.top = NULL;
    s.count = 0;
    return 1;
}

       注释的一句:是生成一个新结点当作栈的头结点,当然可要可不要。然后把栈顶指针置空,让计数器初始化为0。

(4)入栈

int Push(LinkStack& s, int e) {
    LinkStackPtr p = new StackNode;//生成一个新结点
    p->data = e;
    p->next = s.top;//修改指针域
    s.top = p;//修改栈顶指针
    s.count++;//计数器加一
    return 1;
}

       链栈是从上往下遍历的,上面的结点指针域指向下面的结点。栈顶指针一直指向最上面的结点。而且对于链栈来说,基本不存在栈满的情况。

(5)出栈

int Pop(LinkStack& s, int& e) {
    LinkStackPtr p;
    if (s.count == 0)
        return 0;
    e = s.top->data;
    p = s.top;
    s.top = s.top->next;//移动栈顶指针
    delete p;
    s.count--;
    return 1;
}

       栈空的条件:s.count==0,新生成一个指针p指向栈顶结点,移动栈顶指针,删除p指向的结点,计数器减一。

示例:

int main() {
    LinkStack s;
    InitStack(s);
    int n,m;
    cout << "请输入要入栈元素的个数:";
    cin >> n;
    cout << "输入要入栈的元素:";
    for (int i = 0; i < n; i++)
    {
        int e;
        cin >> e;
        Push(s, e);
    }
     cout << "请输入要出栈元素的个数:";
     cin >> m;
     for (int i = 0; i < m; i++)
     {
         int e;
         Pop(s, e);
     }
    cout << "栈里剩余元素为:";
    for (int i = 0; i < s.count; i++) {
        printf("%d ", s.top->data);
        s.top=s.top->next;
    }
    return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值