关于栈和队列的相关操做

一、栈  分为顺序栈和链栈  对应数组和链表数组

top指向栈顶元素,设置空栈为-1;存在一个元素时top=0spa

栈的长度为StackSize.net

定义栈的结构体:指针

 1 #include "stdio.h"
 2 
 3 /* 存储空间初始分配量 */
 4 #define MAXSIZE 20
 5 
 6 /* SElemType类型根据实际状况而定,这里假设为int */
 7 typedef int SElemType;
 8 
 9 /* 顺序栈结构 */
10 typedef struct
11 {
12     SElemType data[MAXSIZE];
13     int top; /* 用于栈顶指针 */
14 }SqStack;
15 
16 int main()
17 {
18 }

进栈操做:pushcode

1 int Push(SqStack * S, SElemType e){
2     if(S->top == MAXSIZE-1){
3         //栈满
4         return 0;
5     }
6     S->top++;
7     S->data[S->top] = e;
8     return 1;
9 }

初始化一个空栈:blog

//初始化栈
int InitStack(SqStack S){
    S->top = -1;
    return 1;
}

栈的遍历:内存

 1 /* 从栈底到栈顶依次对栈中每一个元素显示 */
 2 Status StackTraverse(SqStack S)
 3 {
 4     int i;
 5     i=0;
 6     while(i<=S.top)
 7     {
 8         visit(S.data[i++]);
 9     }
10     printf("\n");
11     return OK;
12 }
13 
14 Status visit(SElemType c)
15 {
16     printf("%d ",c);
17     return OK;
18 }

注:S->top表明着栈对应数组的下标0,1,2 。。。get

出栈:it

1 int Pop(SqStack* S, SElemType* e){
2     if(-1 == S->top){
3         return 0;
4     }
5     *e = S->data[S->top];
6     S->top--;
7     return 1;
8 }

获取栈顶元素:io

1 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;不然返回ERROR */
2 Status GetTop(SqStack S,SElemType *e)
3 {
4     if (S.top==-1)
5         return ERROR;
6     else
7         *e=S.data[S.top];
8     return OK;
9 }

判断栈是否为

1 /* 若栈S为空栈,则返回TRUE,不然返回FALSE */
2 Status StackEmpty(SqStack S)
3 {
4     if (S.top==-1)
5         return TRUE;
6     else
7         return FALSE;
8 }

置空栈:

1 /* 把S置为空栈 */
2 Status ClearStack(SqStack *S)
3 {
4     S->top=-1;
5     return OK;
6 }

二、链栈

链栈对应不含头结点的单链表

top表明指向栈顶的指针,这里和链表中的next合并为一个,当top=null时,链栈为空

定义链栈的结构体:

下面是单链表的结构体:

1 typedef struct Node
2 {
3     ElemType data;
4     struct Node *next;
5 }Node;
6 typedef struct Node *LinkList; /* 定义LinkList */

类似的链栈的结构体为:

1 /* 链栈结构 */
2 typedef struct StackNode
3 {
4     SElemType data;
5     struct StackNode *next;
6 } StackNode,*LinkStackPtr;

这只是链栈一个节点的定义,还须要添加链栈的栈顶指针:

 1 typedef int Status;
 2 /* SElemType类型根据实际状况而定,这里假设为int */
 3 typedef int SElemType;
 4 
 5 /* 链栈结构 */
 6 typedef struct StackNode
 7 {
 8     SElemType data;
 9     struct StackNode *next;
10 } StackNode,*LinkStackPtr;
11 
12 typedef struct
13 {
14     LinkStackPtr top;
15     int count;
16 } LinkStack;

其中count是用来计算栈中元素的个数的,也能够根据须要添加属性等

入栈,其实就是添加新的节点,下面这张图描述的很清楚:

实际上就两步:一、将新的节点next指向原栈顶元素  二、将top指针指向新的节点

1 int Push(LinkStack* L, SElemType e){
2     //首先分配节点
3     LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
4     p->data = e;
5     p->next = S->top;
6     S->top = p;
7     S->count++;
8     return 1;
9 }

初始化空栈:条件count=0,且top为null

 1 /*  构造一个空栈S */
 2 Status InitStack(LinkStack *S)
 3 {
 4     S->top = (LinkStackPtr)malloc(sizeof(StackNode));
 5     if(!S->top)
 6         return ERROR;//分配失败
 7     S->top=NULL;
 8     S->count=0;
 9     return OK;
10 }

遍历的过程和链表彻底相似,这里再也不赘述:

 1 Status StackTraverse(LinkStack S)
 2 {
 3     LinkStackPtr p;
 4     p=S.top;
 5     while(p)
 6     {
 7         visit(p->data);
 8         p=p->next;
 9     }
10     printf("\n");
11     return OK;
12 }
13 
14 Status visit(SElemType c)
15 {
16     printf("%d ",c);
17     return OK;
18 }

出栈操做:这里主要注意一点就是删除的节点要释放掉 核心代码就是S->top = S->top->next;

 1 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;不然返回ERROR */
 2 Status Pop(LinkStack *S,SElemType *e)
 3 {
 4     LinkStackPtr p;
 5     if(StackEmpty(*S))
 6         return ERROR;
 7     *e=S->top->data;
 8     p=S->top;                    /* 将栈顶结点赋值给p,见图中① */
 9     S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中② */
10     free(p);                    /* 释放结点p */
11     S->count--;
12     return OK;
13 }

注:这里的Status是预约义的,这里简化表示int

置空链栈会比顺序栈稍微复杂一些:置空顺序栈只需一步S->top = -1便可,而对于链栈置空实质上就是删除整个链表全部的节点,这里关键的问题就是移动待删除节点指针到下一个位置后,无法直接free掉,这样提及来很差理解,直接看代码:

 1 /* 把S置为空栈 */
 2 Status ClearStack(LinkStack *S)
 3 {
 4     LinkStackPtr p,q;
 5     p=S->top;
 6     while(p)
 7     {
 8         q=p;
 9         p=p->next;
10         free(q);
11     }
12     S->count=0;
13     return OK;
14 }

其实就是先将待删除节点付给一个临时指针,而后当前指针移动到下一个位置后,就能够将这个临时指针给free掉

那这里来分析一下顺序栈和链栈的区别:二者的时间复杂度都为O(1)
顺序栈定位元素更加方便,需提早分配内存区域;链栈在内存充足的状况下大小是无限的,存取定位没有顺序栈快,每一个节点还有指针域,某种程度上增长了空间开销

因此根据不一样状况选择

相关文章
相关标签/搜索