1.顺序栈的结构特点
顺序栈是用顺序存储结构的栈。嗯,贼官方啊,这句话是啥意思呢,就是在内存中用一组地址连续的存储单元依次存放从栈底到栈顶的元素,one by one,都在一块知道不。
栈的声明代码如下:
typedef struct { ElemType data[MaxSize]; int top; //存放栈顶元素在数组中的下标 }SqStack;
开始学的时候真的好迷,干嘛把top叫做指针啦,它又没存放地址来着。。。。不过能通过它来找到对应元素,也算是起了指针的作用吧。
在课本上采用了另一种描述:
就没有ElemType的数组定义了,而是用了两个指针
typedef struct{ ElemType *base; ElemType *top; int MaxSize; //当前已分配的空间 }SqStack;
让base指向栈底不动,emmm,不过用数组下标就可以很容易找到栈底啊,为嘛还要用base来保存它的地址啊(* ̄︶ ̄)
那是因为这种定义里面根本就没有数组啊蠢货!!元素的访问只能通过指针啊!
2.顺序栈的基本算法
1)初始化栈
按照课本上的定义代码,初始化算法
Status InitStack(SqStack &S){ //构造一个空栈 S.base =(ElemType *)malloc(MaxSize*sizeof(ElemType)); if(!S.base) //存储分配失败 exit(0); S.top=S.base; S.stacksize = MaxSize; return 1; }//InitStack;
按照将ElemType有数组的定义里面,初始化操作是这样的
void InitStack(SqStack &s){ s=(SqStack *)malloc(sizeof(SqStack)); s->top = 0; }
要注意到两种算法里面用malloc()函数里面开辟新的空间的不同点
2)进栈Push(SqStack &S,ElemType e);
int Push(SqStack &S,ElemType e){ //插入元素e为新的栈顶元素 if((S.top-S.base) >= S.stacksize){ //栈满,追加储存空间 S.base = (ElemType *)realloc(S.base, (S.stacksize+STACKINCREASEMENT)*sizeof(ElemType)); if(!S.base) exit(0); //存储空间分配失败 S.top = S.base +S.stacksize; //此时stacksize还是原来的值木有变大,指向的是没有增加空间的栈顶 S.stacksize +=STACKINCREASEMENT; } *S.top++ = e; return 1; }//Push
话说,课本上虽然写的很详细,很内啥,健壮??但是真的不好看懂啊,前面那么一长串,就是为了检查空间满没满,满了在加,很容易迷失重点的好嘛!
还有将e赋值的时候,因为用到了top指针,所以是 *top=e; 哟
还是看一下简易版,虽然寒酸了点,但是可以很快get到重点啊
int Push(SqStack &S,ElemType e){ //将数据元素e压入栈顶 if(S.top==MaxSize) return 0; S.elem[S.top]=e; S.top++; return 1; }
其实就是one插入元素two加指针
3)出栈操作Push(SqStack &S, ElemType e);
先来看看课本上的实现
int Pop(SqStack &S,ElemType &e){ //若栈不空,则删除S的栈顶元素,用e返回其值,并返回1,否则返回0 if(S.top == S.base) return 0; e = *--S.top; return 1; }//Pop
这个很好理解啦。要注意的点就是先减指针再取值,不然没有值取啊恍恍惚惚
现在看一下第一种定义里面的实现
int Pop(SqStack &s,ElemType &e){ //若栈不空,则删除S的栈顶元素,用e返回其值,并返回1,否则返回0 if(S.top !=0) return 0; else{ S.top--; e= S.elem[S.top]; } return 1; }
是不是也十分明了呢
4)取栈顶元素GetTop(SqStack &S,ElemType &e)
int GetTop(SqStack &S,ElemType &e){ //若栈不空,则用e返回栈顶元素并返回1,否则返回0 if(S.top == S.base) return 0; e = *(S.top - 1); return 1; }//GetTOP
其实,代码里面有好多巧妙的东西呀,只有打一遍才能发现~比如
num1:为什么这里取元素的时候top指针不是自减一呢?而是top-1
答:因为我们不希望改变top指针的指向啊,用top-1既可以得到栈顶元素,top自己又没有改变,完美!
num2:为什么上面两个代码一个是 e = *--S.top;另一个是 *S.top++ = e;呢(课本上的push和pop算法核心)?
答:因为取元素的时候要先减指针再赋值,而且涉及到运算级的优先问题,*的优先级大于--,所以不能写成,e=--*top;
接下来是另一个定义的取栈顶元素
int GetTop(SqStack &S,ElemType &e){ //若栈不空,则用e返回栈顶元素并返回1,否则返回0 if(S.top == 0) return 0; e=S.elem[S.top-1]; return 1; }
嗯,最基本的操作就在这里了,下一次写应用。