链栈也是一个单链表,插入和删除只能在链表的头部进行,存储结构和单链表一样,每一个结点有两个成员:数据域和指针域
这里也定义一个结构类型typedef,叫做栈的结点 struct StackNode,每个结点包含数据域和指针域,
其中,数据域是用来存放栈中元素的,所以它的类型是栈里头元素的类型SElenType,指针域是指向下一个元素的,所以它指向的类型仍然是这样的一个结构类型,所以我们仍然用这个结构类型来定义这个指针。
这是一个嵌套定义,我们定义结构类型是栈的结点类型,然后我们再用这个类型去定义指向结点的指针类型,叫做*LinkStack。我们用S表示栈这个栈是指向结点的指针型。
链栈中,指针的方向是相反的,与之前的不一样,an里存的不是后继元素,而是前驱元素,
这样存是为了操作方便。其实所有的存储结构不是一成不变的。
头指针指向栈顶,没有头结点(不然操作很麻烦),这里的S就是一个尾指针,因为操作在表尾方便。
链栈不像顺序栈,顺序栈是分配一大块空间存储数组。链栈需要就从内存中找就行,只要内存中还有空间,就不会存在栈满的情况
空栈:一个元素也没有,栈指针不指向任何元素,即头指针是指向空。
链栈的初始化:
准备好空间然后往里头存栈中的元素;对于链栈,我们准备好空间和头指针就行了,有了新结点插入到栈中,头指针指向它就行
构造一个空栈S,让头指针为空
判断链栈是否为空:栈里头没有元素,头指针为空,不指向任何元素
给我一个链栈S,如果S是空,他就是一个空指针,不指向任何元素,那么他就是空栈,返回真
链栈上的入栈
单链表里头指针L是指向第一个结点,不管是首元结点,还是带头结点的时候,他是指向头结点。L既是链表的头指针,又用来称呼这个链表L。S既是指向栈顶元素的头指针。。。
入栈:在栈里头插入新元素,只能放在栈顶,即最后一个元素之后。
首先在内存中找到这样一块空间,然后用指针p指向他,e赋值给data域。插入栈后,原来栈顶的元素变成第二个了:所以给p的next域赋值,赋s。
然后栈顶改变:移动s指针,将指针变量的值赋值给s,s就指向新结点了
首先在内存中分配一块空间StackNode,生成新结点,将新结点的地址赋值给p,p就指向新结点了
然后给data域赋值为e,p->data=e;
然后把他插入到我们的栈,原来的栈顶元素作为它的后继,p->next=S;
最后栈顶指针指向新结点S=p;
链栈的出栈:将栈顶元素输出,将栈顶删除掉,不需要知道第几个结点了,我们规定他只能删除最后一个节点
将data域的值,保留在变量e里头
接下来直接修改指针,下一个元素是栈顶元素,就是将s指针所指的结点的next域(存储了下一结点的地址)的值赋值给s;
在此之前要先有个指针p指向我们要释放的结点,然后s就可以移动了然后将指针p所指的结点释放
如果栈为空,不需要删除了,直接返回错误值
若不为空,就用变量e存储data域的值e=S->data;
然后我们用指针变量p记录下我们要删除的结点P=s;
接下来指针s指向栈顶,因为这个元素已经删了,这个结点的地址在之前s的next域里存着,所以
s=s->next
取栈顶元素
头指针本来就指向栈顶元素,所以直接他的data域的值输出就行
获取栈顶元素,获取的是SElemType的类型,就是返回值类型,给我一个栈,我们就能访问这个元素了
只要头指针不为空,我们就直接返回头指针所指的结点的data域的值,返回后头指针不需发生变化,仍然指向栈顶元素