数据结构学习(三)、栈

栈是一种特殊的线性表。大家可能会有疑问,竟然栈是一种线性表,那为什么还要定义栈呢?因为栈的引入简化了程序设计的问题,

使我们思考范围更小,只需关注top位置。线性表分为顺序存储和链式存储,栈是线性表,所以也有这两种存储方式。同样,

栈作为一种特殊的线性表,也同样存在这两种存储方式。我们先来看栈的顺序存储结构。

顺序栈结构体如下:

#define MAXSIZE /*存储空间初始分配量*/
typedef int ElemType;/*存放的数据类型*/
typedef struct
{
   ElemType data[MAXSIZE];
   int top;  
} SqStack;

现在有一个栈,MAXSIZE为5,则栈普通情况,空栈,满栈的情况如下图所示

顺序栈初始化操作

顺序栈初始化操作实际就是将top指向-1操作

Status InitStack(SqStack *S)
{
    S->top = -1;
    return OK;
}

顺序栈入栈操作

入栈操作实际就是将top增加一,讲新元素赋值给栈顶空间

 

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

 

顺序栈出栈操作

出栈的操作实际就是将栈顶元素辅助给e,栈顶指针减一

Status Pop(SqStack *S,ElemType *e)
{
    if(S->top == NULL)
        return ERROR;
    *e = S->data[S->top];
    S->top--;
    return OK;
}

顺序栈(两栈共享空间)

思路:两栈别人处于数组二端,向中间靠拢。可以想象,只要他们指针不相遇,二个栈就能一直使用。

 

 

其结构体如下:

 

#define MAXSIZE 10
typedef struct
{
    ElemType data[MAXSIZE];
    int top1;
    int top2;
}DuStack;

 

 

 

两栈初始化操作

两栈初始化操作实际就是将top1指向-1,top2指向MAXSIZE操作

 

Status InitStack(DuStack *S)
{
    S->top1 =-1;
    S->top2 =MAXSIZE;
    return OK;
}

 

两栈入栈操作

对于双栈的入栈操作,我们除了要插入元素值外,还需要判断是栈1还是栈2的栈号参数。

/**
    入栈操作
    @params S 共享空间指针变量
    @params e 入栈数据
    @params stackNumber 栈号 1为一号栈 2为二号栈
*/
Status Push(DuStack *S,ElemType e,int stackNumber)
{
    if(S->top1+1 == S->top2)
        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;
}

两栈出栈操作

对于双栈的入栈操作,我们除了要一个接收出栈的值,同样还需要判断是栈1还是栈2的栈号参数。

 

/**
    出栈操作
    @params S 共享空间指针变量
    @params e 出栈数据存放指针变量
    @params stackNumber 栈号 1为一号栈 2为二号栈
*/
Status Pop(DuStack *S,ElemType *e,int stackNumber)
{
    if(stackNumber == 1){
        if(S->top1 == NULL)
            return ERROR;
        *e = S->data[S->top1];
        S->top1--;
    }
    if(stackNumber == 2){
        if(S->top2 == MAXSIZE)
            return ERROR;
        *e = S->data[S->top2];
        S->top2++;
    }
    return OK;
}

 

双栈应用

适合二个栈空间需求有相反关系时。

 

链栈

链栈结构体如下:

 

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

typedef struct LinkStack
{
    int count;
    LinkStackPtr top;
}LinkStack;

 

链栈初始化

初始化操作实际就是将top指针指空,链表计数为零。

 

/*
    初始化共享空间栈,无头结点
    @params LinkStack S 栈指针变量
*/
Status InitStack(LinkStack * S)
{
/*    S->top = (LinkStackPtr *)malloc(sizeof(Node));
    if(!S->top)
        return ERROR;*/
    S->count = 0;
    S->top=NULL;
    return OK;
}

 

链栈进栈操作

进栈操作先分配一个结点,并为结点赋值,把当前栈顶元素赋值给新结点的直接后继,将新的结点赋值给栈顶指针,链表计数加一。

/*
    入栈操作
    @params LinkStack S  栈指针变量
    @params ElemType e  入栈值
*/
Status Push(LinkStack * S,ElemType e)
{
    LinkStackPtr r;
    r = (LinkStackPtr)malloc(sizeof(Node));
    if(!r)
        return ERROR;
    r->data =e;
    r->next = S->top;
    S->top = r;
    S->count ++;
    return OK;
}

链栈出栈操作

出栈操作需先判断是否为空栈,若否,则将栈顶结点值赋给e,将栈顶结点赋值给p,使栈顶指针指向后一个结点,释放p,链表计数减一。

/*
    出栈操作
    @params LinkStack S  栈指针变量
    @params ElemType *e  出栈保存地址
*/
Status Pop(LinkStack * S,ElemType *e)
{
    LinkStackPtr p;
    if(S->top==NULL)
        return ERROR;
    p  = S->top;
    *e = p->data;
    S->top = p->next;
    S->count --;
    free(p);
    return OK;
}

 

posted on 2016-09-23 13:04  会学习的猪  阅读(354)  评论(0编辑  收藏  举报

导航