数据结构(八)栈的链式存储结构
一、栈的链式存储结构,简称为链栈。思路就是把栈顶放在单链表的头部,通常对于链栈来说,是不需要头结点的。
二、链栈基本不存在栈满的情况,除非内存已经没有可以使用的空间。对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top=NULL。
三、栈的链式存储结构的C语言代码实现:
#include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 20 /* 存储空间初始分配量 */ typedef int Status; typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */ /* 链栈结构 */ typedef struct StackNode { SElemType data; struct StackNode *next; }StackNode,*LinkStackPtr; typedef struct { LinkStackPtr top; int count; }LinkStack; Status visit(SElemType c) { printf("%d ",c); return OK; } /* 构造一个空栈S */ Status InitStack(LinkStack *S) { S->top = (LinkStackPtr)malloc(sizeof(StackNode)); if(!S->top) return ERROR; S->top=NULL; S->count=0; return OK; } /* 把S置为空栈 */ Status ClearStack(LinkStack *S) { LinkStackPtr p,q; p=S->top; while(p) { q=p; p=p->next; free(q); } S->count=0; return OK; } /* 若栈S为空栈,则返回TRUE,否则返回FALSE */ Status StackEmpty(LinkStack S) { if (S.count==0) return TRUE; else return FALSE; } /* 返回S的元素个数,即栈的长度 */ int StackLength(LinkStack S) { return S.count; } /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */ Status GetTop(LinkStack S,SElemType *e) { if (S.top==NULL) return ERROR; else *e=S.top->data; return OK; } /* 插入元素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; } /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ Status Pop(LinkStack *S,SElemType *e) { LinkStackPtr p; if(StackEmpty(*S)) return ERROR; *e=S->top->data; p=S->top; /* 将栈顶结点赋值给p,见图中③ */ S->top=S->top->next; /* 使得栈顶指针下移一位,指向后一结点,见图中④ */ free(p); /* 释放结点p */ S->count--; return OK; } Status StackTraverse(LinkStack S) { LinkStackPtr p; p=S.top; while(p) { visit(p->data); p=p->next; } printf("\n"); return OK; } int main() { int j; LinkStack s; int e; if(InitStack(&s)==OK) for(j=1;j<=10;j++) Push(&s,j); printf("栈中元素依次为:"); StackTraverse(s); Pop(&s,&e); printf("弹出的栈顶元素 e=%d\n",e); printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s)); GetTop(s,&e); printf("栈顶元素 e=%d 栈的长度为%d\n",e,StackLength(s)); ClearStack(&s); printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s)); return 0; } 输出为: 栈中元素依次为:10 9 8 7 6 5 4 3 2 1 弹出的栈顶元素 e=10 栈空否:0(1:空 0:否) 栈顶元素 e=9 栈的长度为9 清空栈后,栈空否:1(1:空 0:否)
四、栈的链式存储空间的Java语言代码实现:
- 接口类:
package bigjun.iplab.linkStack; public interface IListStack { // 判断顺序栈是否为空 public boolean isStackEmpty(); // 将一个已经存在的顺序栈置成空表 public void stackClear(); // 求顺序栈的长度 public int stackLength(); // 读取顺序栈的栈顶元素 public int getTopElem() throws Exception; // 在顺序栈中插入元素e public void stackPush(int e); // 删除顺序栈中的栈顶元素 public void stackPop() throws Exception ; // 输出顺序栈中的所有元素 public void stackTraverse(); }
- 节点类:
package bigjun.iplab.linkStack; public class Node { public Integer data; // 存放结点的数据元素的数据域(int类型不能设置null,而Integer类型可以) public Node next; // 存放后继元素的引用 // 可实现初始化一个空的结点 public Node() { this(null, null); } // 可实现构造一个数据域值为指定参数值,而指针域为空的结点 public Node(Integer data) { this(data, null); } // 可实现构造一个数据域和指针域值都为指定参数的结点 public Node(Integer data, Node next) { this.data = data; this.next = next; } }
- 实现类:
package bigjun.iplab.linkStack; public class LinkStack implements IListStack { public Node top; public LinkStack() { top = new Node(); } public boolean isStackEmpty() { return top == null; } public void stackClear() { top = null; } public int stackLength() { Node pNode = top; // 初始化,pNode指向栈顶元素 int length = 0; // length为计数器 while (pNode != null) pNode = pNode.next; ++length; return length; } @Override public int getTopElem() throws Exception { if (!isStackEmpty()) { return top.data; } else { throw new Exception("栈为空,无法获取栈顶元素"); } } public void stackPush(int e) { Node p = new Node(e); p.next = top; top = p; } public void stackPop() throws Exception { if (isStackEmpty()) throw new Exception("栈为空,无法弹出栈顶元素"); else { top = top.next; } } public void stackTraverse() { // 从栈顶元素到栈底元素 Node p = top; System.out.print("此时,链栈中的元素为: "); while (p.data != null) {// 这块有一个问题,就是由于Node类的构造函数的原因,第一个Node的data会为空,如果用p != null的话,就会输出一个null System.out.print(p.data + " "); p = p.next; } System.out.println(); } public static void main(String[] args) throws Exception { LinkStack lStack = new LinkStack(); for (int j = 1; j <= 10; j++) { lStack.stackPush(j); } lStack.stackTraverse(); System.out.println("栈顶元素为: " + lStack.getTopElem()); System.out.println("栈是否为空: " + lStack.isStackEmpty()); lStack.stackPop(); lStack.stackTraverse(); System.out.println("栈顶元素为: " + lStack.getTopElem()); lStack.stackClear(); System.out.println("栈是否为空: " + lStack.isStackEmpty()); } }
- 输出:
此时,链栈中的元素为: 10 9 8 7 6 5 4 3 2 1 栈顶元素为: 10 栈是否为空: false 此时,链栈中的元素为: 9 8 7 6 5 4 3 2 1 栈顶元素为: 9 栈是否为空: true
儿女情长什么的,最影响我们闯荡江湖了。