结点的设计固定直接上代码
#ifndef LINK_NODE_H
#define LINK_NODE_H
// 链表结点类的定义
#include<iostream>
template<class T>
struct LinkNode{
T data;
LinkNode<T> *next;
LinkNode(LinkNode<T>* ptr = NULL){
next = ptr;
}
LinkeNode(T value){
data = value;
next = NULL;
}
};
#endif
此函数是构造函数主要是初始化栈结构相对简单直接上代码
// 构造函数
template<class T>
Linked_stack<T>::Linked_stack(){
count = 0;
top = NULL;
}
析构函数,要进行的操作是释放存储空间。我是用的是clear()函数,clear()函数是用来清空栈的,完全可以在此处使用
// 构造函数
template<class T>
Linked_stack<T>::~Linked_stack(){
clear();
}
判断栈是否为空,通过count来进行判断
template<class T>
bool Linked_stack<T>::empty()
{
return count==0;
}
将元素压入栈,因为是链式存储结构因此一般不会出现栈空间不足的情况,这里可以加个判断
template<class T>
error_code Linked_stack<T>::push(T x){
LinkNode<T>* s = new LinkNode<T>(x);
if(s != NULL)
{
s->next = top;
top = s;
count++;
return success;
}
else{
return fail;
}
}
这里需要理清楚指针与结点之间的关系。指针是指向存储空间而不是存储空间,通过指针能访问存储空间。这里的top是个指针他始终指向栈顶元素,存储的是栈顶元素的首地址。因此通过top能访问栈顶元素。插入一个新结点在栈顶那么就需要将top指针指向该新结点,并将原先的栈顶结点作为新结点的下一个结点。
取栈顶元素并将其存储在x中,这个操作不是很难
template<class T>
error_code Linked_stack<T>::get_pop(T& x)
{
if(empty())
{
return fail;
}
else{
x = top->data;
return success;
}
}
删除栈顶元素
template<class T>
error_code Linked_stack<T>::pop()
{
if(empty())
{
return fail;
}
else{
LinkNode<T>* temp = top;
top = top->next;
delete temp;
count--;
}
}
此处首先判断栈是否为空,然后进行删除操作。删除栈顶元素,即删除栈顶结点并以其后继结点作为栈顶结点,那么需要声明一个临时变量储存未删除前的栈顶地址,然后再进行删除操作。
非常简单直接上代码
template<class T>
int Linked_stack<T>::get_size()
{
return count;
}
也非常简单
template<class T>
void Linked_stack<T>::clear()
{
while(!empty())
{
pop();
}
}
#ifndef LINKED_STACK_H
#define LINKED_STACK_H
#include "LinkNode.h"
#include<iostream>
// g++编译器不支持将模板文件分离编译因此需要将模板函数的实现写在类定义的头文件内
using namespace std;
enum error_code{
success,
fail
};
template <class T>
class Linked_stack{
public:
Linked_stack(){
count = 0;
top = NULL;
}; // 初始默认构造函数
Linked_stack(T *value,int n); // 传入数组根据数组建立栈
~Linked_stack(); // 析构函数
public:
error_code push(T x); // 将新元素压入栈
error_code pop(); // 栈顶元素出栈,并将该值保存到x中
error_code get_pop(T& x); // 获取栈顶元素,并将该值保存到x
bool empty(); // 栈是否为空
int get_size(); // 获取当前栈元素个数
void clear(); // 清空栈内容
private:
LinkNode<T> *top; // 栈顶指针
int count; // 记录栈内元素个数
};
#endif
#include<iostream>
using namespace std;
// 构造函数
template <class T>
Linked_stack<T>::Linked_stack(T *value,int n){
count = 0;
for(int i=0;i<n;i++){
push(value[i]);
count++;
}
}
template <class T>
Linked_stack<T>::~Linked_stack(){
clear();
}
// 栈顶元素出栈并将该元素的值保存至x
template <class T>
error_code Linked_stack<T>::pop(){
// 首先判断栈是否为空
if(empty() == true){
return fail;
}
else{
int x;
LinkNode<T> *currentNode = top;
top = top->next;
x = currentNode->data;
delete currentNode;
count--;
return success;
}
}
// 新元素入栈
template <class T>
error_code Linked_stack<T>::push(T x){
LinkNode<T> *newNode = new LinkNode<T>();
if(newNode == NULL){
return fail;
}
newNode->next = top;
newNode->data = x;
top = newNode;
count++;
return success;
}
//获取栈顶元素
template <class T>
error_code Linked_stack<T>::get_pop(T &x){
// 首先判断栈是否为空
if(empty() == true){
return fail;
}
else{
x = top->data;
return success;
}
}
template <class T>
bool Linked_stack<T>::empty(){
if(count == 0)
return true;
return false;
}
template <class T>
int Linked_stack<T>::get_size(){
return count;
}
template <class T>
void Linked_stack<T>::clear(){
LinkNode<T> *curNode = NULL;
while(top != NULL){
curNode = top;
top = top->next;
delete curNode;
}
count = 0;
}
这里有一个小细节就是使用模板类的话,类中函数的实现要写在头文件内,不然g++编译器无法找到类中函数的实现。
首先要明确,队列的插入即入队操作是在尾部进行,而插入操作需要知道当前链表的尾结点从而向其插入元素。队列的删除即出队操作是在头部进行,因而设置在链表头。
此处分为两种初始化情况对应还是有一定的差别的
#ifndef LINK_NODE_H
#define LINK_NODE_H
// 队列结点类的定义
#include<iostream>
template<class T>
struct Node{
T data;
Node<T> *next;
Node(Node<T>* ptr = NULL){
next = ptr;
}
Node(T value){
data = value;
next = NULL;
}
};
#endif
这里如上面所说有两种设计此处分别给出
template<class T>
Linked_queue<T>::Linked_queue(){
front = NULL;
rear = NULL;
count = 0;
}
template<class T>
Linked_queue<T>::Linked_queue(){
Node<T>* head = new Node<T>();
front = head;
rear = head;
count = 0;
}
析构函数由于有两种不同的初始化方式,那么此时析构函数也对应两种不同的操作
template<class T>
Linkde_queue<T>::~Linked_queue()
{
while(!empty())
{
serve(); 删除元素
}
}
Linkde_queue<T>::~Linked_queue()
{
while(!empty())
{
serve();
}
delete front; // 删除头结点
}
判断队列是否为空,此处根据count是否为零判断即可,也可以根据front是否与rear相等来判断
template<class T>
bool Linked_queue<T>::empty()
{
return count == 0;
}
template<class T>
error_code Linked_queue<T>::get_front(T& x)
{
if(empty())
{
return fail;
}
x = front->data;
return success;
}
template<class T>
error_code Linked_queue<T>::get_front(T& x)
{
if(empty())
{
return fail;
}
x = front->next->data;
return success;
}
向队列中添加元素,那么此时更分成两种情况,一种为不含头结点一种为含头结点
template<class T>
error_code Linked_queue<T>::append(T x)
{
// 需要加一个判断对于队列为空的情况
if(empty())
{
Node<T>* newNode = new Node<T>(x);
newNode->next = NULL;
front = newNode;
rear = newNode;
count++;
return success;
}
Node<T>* newNode = new Node<T>(x);
newNode->next = NULL;
rear->next = newNode; // 连接
rear = newNode;
count++;
return success;
}
template<class T>
error_code Linked_queue<T>::append(T x)
{
Node<T>* newNode = new Node<T>(x);
newNode->next = NULL;
rear->next = newNode; // 连接
rear = newNode;
count++;
return success;
}
获取队列尾部元素
template<class T>
error_code Linked_queue<T>::get_rear(T& x)
{
if(empty())
{
return fail;
}
x = rear->data;
return success;
}
删除队头元素这里也要分为两种情况进行讨论
template<class T>
error_code Linked_queue<T>::serve()
{
if(empty())
{
return fail;
}
Node<T>* temp = front;
front = front->next;
delete temp;
count--;
return success;
}
template<class T>
error_code Linked_queue<T>::serve()
{
if(empty())
{
return fail;
}
Node<T>* temp = front->next;
front->next = temp->next;
delete temp;
count--;
if(front->next==NULL)
{
rear = front; // 此时队列中无元素,如果不这样的话rear指向的存储空间已经删除,rear将无意义
}
return success;
}