【读书笔记】大话数据结构之 栈(1)

1 什么是栈(stack)?

栈是限定仅在表尾进行插入和删除操作的线性表

2 有什么特点?

1)只允许在栈顶进行插入和删除操作
2)栈有两端,允许操作的称为栈顶,另一端称为栈底
3)允许空栈,即不含任何数据元素
4)栈是后进先出的线性表,LIFO(Last In First Out)结构
5)特殊的线性表

3 有哪些操作?

1)InitStack(*s):初始化操作,建立一个空栈S
2)DestoryStack(*s):若栈存在,则销毁它
3)ClearStack(*s):清空栈
4)StackEmpty(s):判断栈是否为空
5)GetTop(S,*e):若栈存在且非空,用e返回s栈的栈顶元素
6)Push(*s,e):若栈s存在,插入新元素e到栈s中并成为栈顶元素
7)Pop(*s,*e):删除栈s中的栈顶元素,并用e返回其值
8)StackLength(s):返回栈s的元素个数

4 有什么存储结构?

4.1 栈的顺序存储结构

一个简化的顺序存储线性表,以下定义一下栈的结构:

#define MAXSIZE 10;
#define OK 1;
#define EEROR 0;

typedef int Status;
typedef int ElemType;/*ElemTypel的类型可根据实际情况而定*/
typedef struct Stack{
    ElemType data[MAXSIZE];
    int top;               //用于栈顶指针
} mStack;

4.1.1 进栈操作

1)步骤:
a 判断传入的栈是否满栈了,若是返回ERROR
b 将top加1,然后将data[top] 的值赋为插入值e,返回OK;
2)代码如下:

Status Push(Stack *s,ElemType e){
    if( s->top == MAXSIZE-1){
        reuturn ERROR;
    }
    s->top++;
    s->data[s->top] = e;
    return OK;
}

3)时间复杂度O(1);

4.1.2 出栈操作

1)步骤:
a 判断传入的栈是否为空,若是则返回ERROR
b 获取删除的值,并将top减1;
2)代码如下:

Status Pop(Stack *s,ElemType *e){
    if( s->top == -1){
    return ERROR;
    }

    *e = s->data[s->top];
    s->top--;
    return OK;
}

3)时间复杂度O(1);

4.1.3 两栈共享空间

这里写图片描述
注:假设一个栈长度为n,那么两栈总长为2n,初始化时top1指向0,top2指向2n-1

4.1.3.1 特点

a 具有一定的“动态扩容能力”,即当top2指向2n-1时,栈1则相当于拥有2n的长度。
b 满栈状态,top2 = top1+1;
定义一个两栈共享的栈结构:

typedef struct DoubleStack{
    ElemType data[MAXSIZE];
    int top1;
    int top2;
}

4.1.3.2 进栈操作

1)步骤
a 判断当前栈是否满栈,若是则返回ERROR
b 判断要插入哪个栈,执行插入操作
2)代码如下:

Status Push(DoubleStack *s ,ElemType e ,int statckNumber){
    if(s->top2 == s->top1+1){
    return ERROR;
    }
    if(stackNumber == 1){
        s->top1++;
        s->data[s->top1] = e;
    }else if(stackNumber == 2){
        s->top2--;
        s->data[s->top2] = e;
    }
    return OK;
}

4.1.3.3出栈操作

1)步骤
a 判断要删除哪个栈的元素,然后判断该栈是否空栈
b 若是则返回ERROR,否则执行删除操作
2)代码如下:

Status Pop(DoubleStack *s, ElemType *e,int stackNumber){
    if(stackNumber == 1){
        if(s->top1 == -1){
            rerurn ERROR;
        }else{
            *e = s->data[s->top1];
            s->top1--;
        }
    }else if(stackNumber == 2){
        if(s->top2 == MAXSIZE){
            return ERROR;
        }else{
            *e = s->data[s->top2];
            s->top2++;
        }
    }
    return OK;
}

注意:这样的数据结构适用于两个栈有彼消此长关系的情形,如股票的买入和卖出总量保持不变的,而且数据类型是相同的,否则意义不大

4.2 栈的链式存储结构

栈与链表相结合,栈的栈顶与链表的头指针相结合,定义一个链栈的结构:

typedef struct StackNode{
    ElemType data;
    struct StackNode *next;
}StackNode,*LinkStackPtr;

typedef struct LinkStack{
    LinkStackPtr top;
    int count;
}

4.2.1 进栈操作

1)步骤
a 为要插入的元素开辟空间p
b 将e赋值给p->data
c 将p->next = s->top
d 将s->top = p,s->count加1,返回OK
2)代码如下:

Status Push(LinkStack *s,ElemType e){
    LinkStackPtr p = (LinkStackPtr)malloc(sizeOf(StackNode));//开辟空间
    p->data = e;//赋值
    p->next = s->top;//把当前栈顶元素赋值给新结点的直接后继

    s->top = p;头指针赋值为p
    s->count++;
    return OK;
}

4.2.2 出栈操作

1)步骤
a 判断当前栈是否为空栈,若是则返回ERROR
b 定义一个p = s->top,释放p
c 将s->top = s->top->next;
d 返回OK;
2)代码如下:

Status Pop(LinkStack *s, ElemType *e){

    LinkStackPtr p;
    if(s->top == NULL){
        return ERROR;
    }
    p = s->top;
    *e = p->data;
    free(p);
    s->top = s->top->next;
    return OK;
}

5 相关问题

1)最先进栈的元素,是不是只能最后出栈?
答:不一定,栈对线性表的插入和删除的位置进行了限制,但没有对元素的进出时间进行限制,只需要保证每次出栈的元素是栈顶元素。

6 相关练习

1 用两个栈模拟一个队列
题目解析:http://blog.csdn.net/u011812294/article/details/49130465
2 输入两个整数序列,第一个表示栈的压入顺序,请判断第二序列是否为该栈的弹出序列,假设压入栈的所有数字均不相等。
3 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数,在该栈中,调用、push和pop的时间复杂度为O(1);

题目来自剑指offer,解析在下一篇博文中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值