一.引入
通常链栈用单链表表示,因此其结点结构与单链表的结点结构相同。因为只能在栈顶执行插入和删除操作,显然以单链表的头部做栈顶是最方便地,而且没有必要像单链表那样为了运算方便附加一个头结点。
二.算法设计
LinkedStack.h
#ifndef SRC_LINKEDSTACK_H_
#define SRC_LINKEDSTACK_H_
/*
* 结点:
* data:数据域,存储数据元素
* next:指针域,存储该结点的后继结点的地址
*/
template <class T>
struct Node{
T data;
Node<T> *next;
};
template <class T>
class LinkedStack{
public:
LinkedStack();//无参构造器
LinkedStack(T array[],int length);//有参构造器
virtual ~LinkedStack();//析构函数
int getLength();//取当前栈的长度
void push(T value);//入栈
T pop();//出栈
T getTop();//取栈顶元素
void getAll();//遍历栈的全部元素
bool isEmpty();//判断是否栈空
private:
Node<T> *top;//栈顶指针
int length;//当前栈的长度
};
#endif
三.详细设计(C++)
LinkedStack.cpp
#include "LinkedStack.h"
#include <iostream>
using namespace std;
/*
* 无参构造器:
* 1.栈顶指针 top 置为 NULL
* 2.当前栈的长度置为 0
*/
template <class T>
LinkedStack<T>::LinkedStack(){
top = NULL;
length = 0;
}
/*
* 有参构造器:
* 1.栈顶指针 top 置为 NULL
* 2.创建一个结点 node 置为 NULL
* 3.循环:
* ①.为结点 node 申请空间
* ②.把数组的值存储在结点 node 的 data 域中
* ③.把栈顶指针 top 指向的结点的地址存储在 结点 node 的 next 域中
* ④.栈顶指针 top 指向结点 node
* 4.记录当前栈的长度
*/
template <class T>
LinkedStack<T>::LinkedStack(T array[],int length){
top = NULL;
Node<T> *node = NULL;
for(int i = 0;i < length;i++){
node = new Node<T>;
node->data = array[i];
node->next = top;
top = node;
}
this->length = length;
}
/*
* 析构函数:
* 1.创建一个结点 deleteNode 置为 NULL
* 2.循环:
* ①.结点 deleteNode 指向栈顶结点
* ②.栈顶指针 top 指向栈顶结点的下一个结点
* ③.删除栈顶结点
* ④.当前栈的长度减一
*/
template <class T>
LinkedStack<T>::~LinkedStack(){
Node<T> *deleteNode = NULL;
while(!isEmpty()){
deleteNode = top;
top = top->next;
delete deleteNode;
length--;
}
}
/*
* 取当前栈的长度:
* 返回当前栈的长度
*/
template <class T>
int LinkedStack<T>::getLength(){
return length;
}
/*
* 入栈:
* 1.创建一个结点 pushNode ,申请空间
* 2.把 value 存储在结点 pushNode 的 data 域中
* 3.结点 pushNode 与原来的栈顶元素相连
* 4.栈顶指针 top 指向结点 pushNode ,即结点 pushNode 成为栈顶元素
* 5.当前栈的长度加一
*/
template <class T>
void LinkedStack<T>::push(T value){
Node<T> *pushNode = new Node<T>;
pushNode->data = value;
pushNode->next = top;
top = pushNode;
length++;
}
/*
* 出栈:
* 1.判断是否栈空,若是则返回 -1,否则
* 2.创建一个结点 popNode ,其指向栈顶结点
* 3.创建一个变量 popNodeValue ,其记录栈顶结点存储的元素
* 4.栈顶指针 top 指向栈顶结点的下一个结点
* 5.删除栈顶结点 popNode
* 6.返回栈顶结点存储的元素 popNodeValue
*/
template <class T>
T LinkedStack<T>::pop(){
if(isEmpty()){
cout<<"栈空!"<<endl;
return -1;
}
Node<T> *popNode = top;
T popNodeValue = popNode->data;
top = top->next;
delete popNode;
length--;
return popNodeValue;
}
/*
* 取栈顶元素:
* 1.判断是否栈空,若是则返回 -1,否则
* 2.返回栈顶结点存储的元素
* 注意:并不删除栈顶结点
*/
template <class T>
T LinkedStack<T>::getTop(){
if(isEmpty()){
cout<<"栈空!"<<endl;
return -1;
}
return top->data;
}
/*
* 遍历栈的全部元素:
* 1.判断是否栈空,若是则返回,否则
* 2.创建一个结点 node ,其指向栈顶结点
* 3.循环:当未到达栈底结点时
* ①.输出栈顶结点存储的元素
* ②.结点 node 指向下一个结点
* 4.输出栈底结点存储的元素
*/
template <class T>
void LinkedStack<T>::getAll(){
if(isEmpty()){
cout<<"栈空!"<<endl;
return;
}
Node<T> *node = top;
while(node->next != NULL){
cout<<node->data<<" ";
node = node->next;
}
cout<<node->data<<endl;
}
/*
* 判断是否栈空:
* 若栈顶指针 top 为 NULL 则返回 true ,否则返回 false
*/
template <class T>
bool LinkedStack<T>::isEmpty(){
return top == NULL ? true : false;
}
四.测试
TestLinkedStack.cpp
#include "LinkedStack.h"
#include "LinkedStack.cpp"
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
int arr[] = {0,1,2,3,4};
cout<<"创建对象:0、1、2、3、4 依次入栈 "<<endl;
LinkedStack<int> linkedStack(arr,5);
cout<<"遍历栈内的元素:";
linkedStack.getAll();
cout<<"当前栈的长度:";
cout<<linkedStack.getLength()<<endl;
cout<<"当前的栈顶元素:"<<linkedStack.getTop()<<endl;
cout<<endl;
while(!linkedStack.isEmpty()){
cout<<linkedStack.pop()<<"出栈!"<<endl;
cout<<"遍历栈内的元素:";
linkedStack.getAll();
cout<<"当前栈的长度:";
cout<<linkedStack.getLength()<<endl;
cout<<"当前的栈顶元素:"<<linkedStack.getTop()<<endl;
cout<<endl;
}
cout<<endl;
for(int i = 0;i < 10;i++){
cout<<i<<"入栈!"<<endl;
linkedStack.push(i);
}
cout<<"遍历栈内的元素:";
linkedStack.getAll();
cout<<"当前栈的长度:";
cout<<linkedStack.getLength()<<endl;
cout<<"当前的栈顶元素:"<<linkedStack.getTop()<<endl;
cout<<endl;
cout<<"销毁栈!"<<endl;
linkedStack.~LinkedStack();
return 0;
}
五.运行结果