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

来源:互联网 发布:淘宝客佣金 编辑:程序博客网 时间:2024/05/18 02:55

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
原创粉丝点击