栈的简要介绍

文章目录

背景介绍

最近又看了一遍大话数据结构,在这里对第四章——栈进行一些总结。

定义,栈是限定在表尾进行插入删除的线性表。其中进行插入删除操作的一端称作栈顶,另一端为栈底,无元素称为空栈。
栈的抽象数据类型:
栈的简要介绍

栈的顺序存储结构

结构代码如下:

typedef int SElemType; 	/* SElemType类型根据实际情况而定,这里假设为int */

/* 顺序栈结构 */
typedef struct
{
        SElemType data[MAXSIZE];
        int top; 		/* 用于栈顶指针 */
}SqStack;		//sq即sequence,表示顺序的意思,sqlist表示顺序表,SqStack表示顺序栈。

可以看出,顺序表(sqlist)跟顺序栈(SqStack)的存储结构区别不大,只是将SqList中length替换成top,其中top指向栈顶的元素,比如,当栈内存在一个元素时,即data[0]存在时,top为0,当栈内无元素时,top为-1.
另外,栈也需要通过初始化函数 InitStact ( *L ) ,建立一个空的栈L。
各类相应操作函数可在网上查询,这里不复赘言。

栈的小技巧——两栈共享空间

定义:简单来说,就是使用的两个栈共享同一个存储空间
代码如下:

/* 两栈共享空间结构 */
typedef struct 
{
        SElemType data[MAXSIZE];
        int top1;	/* 栈1栈顶指针 */
        int top2;	/* 栈2栈顶指针 */
}SqDoubleStack;

可以看出两栈的结构相对于顺序栈SqStack只是多了一个top变量。
使用函数InitStack,初始化两栈栈

/*  构造一个空栈S */
Status InitStack(SqDoubleStack *S)
{ 
        S->top1=-1;
        S->top2=MAXSIZE;
        return OK;
}

此时栈的情况如下:
栈的简要介绍
在这里,n就是MAXSIZE,可以看出两栈的结构相对于顺序栈SqStack只是多了一个top2变量。在栈中,栈1与栈2实际上是同一个栈,共享同一个存储空间,即数组data( SElemType data[MAXSIZE];),只是人为的在概念上将它划分为两个栈(栈1与栈2)。
当元素进入栈1时, top1加一,当元素从栈1出去时,top1减一,与顺序栈SqStack中插入删除并无太大关系,当元素进入栈2时,top2减1,当元素从栈2出去时,top2加一,简单来说,就是栈1 以数组左端为栈底,向右端延伸,栈2以数组右端为栈底,向左端延伸
附上插入的代码,便与加深对双栈的理解。

/* 插入元素e为新的栈顶元素 */
//stackNumber,说明插入的栈为1或2.
Status Push(SqDoubleStack *S,SElemType e,int stackNumber)
{
        if (S->top1+1==S->top2)	/* 栈已满,不能再push新元素了 */
                return ERROR;	
        if (stackNumber==1)			/* 栈1有元素进栈 */
                S->data[++S->top1]=e; /* 若是栈1则先top1+1后给数组元素赋值。 */
        else if (stackNumber==2)	/* 栈2有元素进栈 */
                S->data[--S->top2]=e; /* 若是栈2则先top2-1后给数组元素赋值。 */
        return OK;
}

栈满的判定条件:
容易发现,当top1+1=top2时,栈满,此时不能再插入元素。

栈的链式存储结构

结构代码如下:

/* 链栈结构 */
typedef struct StackNode
{
        SElemType data;
        struct StackNode *next;
}StackNode,*LinkStackPtr;


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

可以看出,其实链栈与单链表LinkList并没有太大的区别,其中LinkStackPtr top就相当于单链表LinkList的头指针,只不过单链表LinkList头指针一般冠以链表名,而top指向的是尾结点,并且多了一个计数器count,形成一个链栈结构LinkStact。另外,插句题外话,顺序表SqList中有个length,也是类似作用。
链栈初始化:

/*  构造一个空栈S */
Status InitStack(LinkStack *S)
{ 
        S->top = (LinkStackPtr)malloc(sizeof(StackNode));
        if(!S->top)
                return ERROR;
        S->top=NULL;
        S->count=0;
        return OK;
}

另外值得注意的是,单链表中next指针指向的下一个结点,即后继,但链栈中next指针指向的结点,实际上是前一个元素,即前驱。
附上流程图一张
栈的简要介绍
附上插入元素的函数代码,便与理解:

/* 插入元素e为新的栈顶元素 */
Status Push(LinkStack *S,SElemType e)
{
        LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
        s->data=e; 
        s->next=S->top;	/* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
        S->top=s;         /* 将新的结点s赋值给栈顶指针,见图中② */
        S->count++;
        return OK;
}

其他各类相应操作函数可在网上查询,这里不复赘言。

上一篇:day4 crm客户管理之初始化权限校验


下一篇:LeetCode 36. Valid Sudoku (Medium)