您的位置:首页 > 理论基础 > 数据结构算法

数据结构——栈与队列

2018-02-01 11:38 169 查看

  栈与队列

栈是种非常重要的数据结构,因为其特殊的数据储存结构,在计算机编程中有非常广泛的应用。比如说一些基于堆栈的编程语言,
程序的运行就是基于栈式结构的,比如说Java程序,当一个方法调用另一个方法时,就会把当前方法的输入、输出类型和一些变量存入
栈帧中,然后调用另一个方法,这个方法就成为另一个栈帧,压在调用方法栈帧上方,当被调用方法返回时,就把这个方法的栈帧Pop
出来,调用方法回到调用地点继续执行,这就是利用栈式结构先进后出的特性实现的方法调用层次结构。当然栈还有很多其他的应用场
景,比如说利用栈来计算四则运算,把计算式压入栈,当遇到回括号时就可以把数据从栈中取出来进行相应的部分计算,再把部分计算
结果压入栈,继续计算,最后栈中只剩的最后一个数就是计算结果。
由于栈先进后出的储存特性,因此栈的操作也比较简单,基本上提供入栈、出栈、获取栈顶元素和清空操作即可。和线性表一样,
栈也有顺序储存结构和链式储存结构两种实现方法。
下面是栈数据结构的接口定义
#pragma once
#ifndef STACK_H
#define STACK_H
namespace dataStructure {
template<typename T>
class Stack {
public:
Stack() {};
~Stack() {};
virtual int Length() const = 0;
virtual bool Empty() const = 0;
virtual void Clear() = 0;
virtual void Traverse(void(*visit)(T &t))const = 0;
virtual bool Push(const T &am
4000
p;t) = 0;
virtual bool Top(T &t)const = 0;
virtual bool Pop(T &t) = 0;
};
}
#endif


当用顺序储存结构进行实现时,可以固定栈的大小,很多时候栈用于做递归调用,栈如果太大的话,可能会占用太多内存导致系统
负荷过大。

下面的代码是基于顺序储存结构的栈实现
#pragma once
#ifndef ARRAYSTACK_H
#define ARRAYSTACK_H
#include "stack.h"
namespace dataStructure {
template<typename T>
class ArrayStack :public Stack<T> {
public:
ArrayStack();
~ArrayStack();
int Length() const;
bool Empty() const;
void Clear();
void Traverse(void(*visit)(T &t)) const;
bool Push(const T &t);
bool Top(T &t)const;
bool Pop(T &t);

private:
const int MAX_SIZE = 1000;//最大容量,不能扩容
T *data;
int size;
};

template<typename T>
ArrayStack<T>::ArrayStack() {
data = new T[MAX_SIZE];
size = 0;
}

template<typename T>
ArrayStack<T>::~ArrayStack() {
delete data;
}
template<typename T>
int ArrayStack<T>::Length() const {
return size;
}
template<typename T>
bool ArrayStack<T>::Empty() const
{
return size == 0;
}

template<typename T>
void ArrayStack<T>::Clear()
{
size = 0;
}

template<typename T>
void ArrayStack<T>::Traverse(void(*visit)(T &t)) const
{
for (int i = size - 1;i >= 0;i--)
{
visit(data[i]);
}
}

template<typename T>
bool ArrayStack<T>::Push(const T &t)
{
if(size >= MAX_SIZE)
{
return false;
}

data[size++] = t;
return true;
}

template<typename T>
bool ArrayStack<T>::Top(T &t)const
{
if (size > 0)
{
t = data[size - 1];
return true;
}

return false;
}
template<typename T>
bool ArrayStack<T>::Pop(T &t)
{
if(size > 0)
{
t = data[size - 1];
--size;
return true;
}
return false;
}
}
#endif
采用链式储存结构实现
#pragma once
#ifndef LINKSTACK_H
#define LINKSTACK_H
#include "stack.h"
namespace dataStructure {
template<typename T>
struct Node
{
T data;
Node<T> *bottom = NULL;
};
template<typename T>
class LinkStack :public Stack<T> {
public:
LinkStack();
~LinkStack();
int Length() const;
bool Empty() const;
void Clear();
void Traverse(void(*visit)(T &t)) const;
bool Push(const T &t);
bool Top(T &t)const;
bool Pop(T &t);

private:
Node<T> *topp;//表示栈顶元素上面的一个节点
int size;
};

template<typename T>
LinkStack<T>::LinkStack() {
topp = new Node<T>;
topp->bottom = NULL;
size = 0;
}

template<typename T>
LinkStack<T>::~LinkStack() {
Node<T> *node = topp;
Node<T> *bottom = topp->bottom;
while (topp)
{
delete topp;
topp = bottom;
bottom = topp->bottom;
}
size = 0;
}
template<typename T>
int LinkStack<T>::Length() const {
return size;
}
template<typename T>
bool LinkStack<T>::Empty() const
{
return size == 0;
}

template<typename T>
void LinkStack<T>::Clear()
{
size = 0;
}

template<typename T>
void LinkStack<T>::Traverse(void(*visit)(T &t)) const
{
Node<T> *node = topp->bottom;
while (node)
{
visit(node->data);
node = node->bottom;
}
}

template<typename T>
bool LinkStack<T>::Push(const T &t)
{
Node<T>* newNode = new Node <T> ;
newNode->data = t;
newNode->bottom = topp->bottom;
topp->bottom = newNode;
++size;
return true;
}

template<typename T>
bool LinkStack<T>::Top(T &t)const
{
if(size > 0)
{

t = topp->bottom->data;
return true;
}
return false;
}
template<typename T>
bool LinkStack<T>::Pop(T &t)
{
Node<T>* node;
if(size > 0)
{
node = topp->bottom;
topp->bottom = node->bottom;
t = node->data;
delete node;
--size;
return true;
}
return false;
}
}
#endif
#include "stdafx.h"
#include "arraystack.h"
#include "linkstack.h"
#include <iostream>
using namespace std;
using namespace dataStructure;
void visit(int &t)
{
cout << t << ",";
}
int main()
{
Stack<int> *stack = new LinkStack<int>;
stack->Push(1);
stack->Push(2);
stack->Push(3);
stack->Traverse(visit);
cout << endl;
int i;
cout << stack->Top(i) << endl;
cout << i << endl;
stack->Pop(i);
cout << i << endl;
stack->Traverse(visit);
system("pause");
return 0;
}


       队列和栈一样,也是一种具有特性的数据结构,和栈相反,队列的特性是先进先出。这种先进先出的特性在很多场景也会经常用到,比如在进程调用过程中,为了防止进程饿死,就可以采用先进先出的策略让每个进行都有上CPU的机会。
      并且队列还可以实现优先队列,就是可以按特定的排序规则,让队列并不完全按先进先出,而是进行了相应的排序,这种实现在进程调度的过程中可以实现有优先级的先进先出策略。一来可以让优先级高的更有机会拥有CPU资源,二来又不会让优先级低的饿死。实现普通队列用实现线性表的策略就可以,采用顺序储存结构或者链式储存结构,但优先队列如果用这两种方式来实现的话,就会非常复杂,因为要涉及到排序的问题,每次添加一个元素进优先队列都可以会破坏原队列的优先顺序,可以每次添加进队列都要进行排序。但有更优的储存策略,就是使用堆来储存。堆是一种二叉树,分为最大堆与最小堆,最大堆的特点是根节点的值大于子节点,而最小堆则相反,根节点的值小于子节点。基于这种特点,在优先队列实现时,添加新元素到队列中时,就可以根据堆的相应形态做适应变换来维持堆的稳定,变换后堆仍然具有稳定规则。但在取元素的时候就会非常方法,比如队列是增序的话,也就是值越大的就让在队列的队头,那么采用最大堆,每次取队首元素就只需要把堆的根节点取出来,然后再变换使堆保持稳定。而这种变换比排序的效率高很多,因而采用堆来作为优先队列的底层数据结构比顺序和链式储存结构都要高效得多。
       下面的代码是分别使用顺序储存结构和链式储存结构来实现普通队列。
        首先还是队列的接口定义
#pragma once
#ifndef QUEUE_H
#define QUEUE_H
namespace dataStructure
{
template<typename T>
class Queue
{
public:
Queue() {};
~Queue() {};
virtual int Length()const = 0;
virtual bool Empty() const = 0;
virtual void Clear() = 0;
virtual void Traverse(void(*visit)(T &t))const = 0;
virtual bool OutQueue(T &t) = 0;
virtual bool GetHead(T &t) = 0;
virtual bool InQueue(const T &t) = 0;
};
}
#endif;


然后是顺序储存结构实现的队列
#pragma once
#ifndef ARRAYQUEUE_H
#define ARRAYQUEUE_H
#include "queue.h"
namespace dataStructure
{
template<typename T>
class ArrayQueue:public Queue<T>
{
public:
ArrayQueue();
~ArrayQueue();
int Length()const;
bool Empty() const;
void Clear();
void Traverse(void(*visit)(T &t))const;
bool OutQueue(T &t);
bool GetHead(T &t);
bool InQueue(const T &t);
private:
const int MAX_SIZE = 1000;
T *data;
int size;
};

template<typename T>
ArrayQueue<T>::ArrayQueue()
{
data = new T[MAX_SIZE];
size = 0;
}

template<typename T>
ArrayQueue<T>::~ArrayQueue()
{
delete data;
size = 0;
}

template<typename T>
int ArrayQueue<T>::Length() const
{
return size;
}

template<typename T>
bool ArrayQueue<T>::Empty() const
{
return size == 0;
}

template<typename T>
void ArrayQueue<T>::Clear()
{
size = 0;
}

template<typename T>
void ArrayQueue<T>::Traverse(void(*visit)(T &t))const
{
for (int i = 0;i < size;i++) {
visit(data[i]);
}
}

template<typename T>
bool ArrayQueue<T>::OutQueue(T &t)
{
if(size > 0)
{
t = data[0];
for (int i = 1;i < size;i++) {
data[i - 1] = data[i];
}
--size;
return true;
}
return false;
}

template<typename T>
bool ArrayQueue<T>::GetHead(T &t)
{
if (size > 0)
{
t = data[0];
return true;
}
return false;
}

template<typename T>
bool ArrayQueue<T>::InQueue(const T &t)
{
if (size < MAX_SIZE)
{
data[size++] = t;
return true;
}
return false;
}
}
#endif;


再然后是链式储存结构实现的队列,并且内部使用了链式线性表来作为底层数据结构
#pragma once
#ifndef LINKQUEUE_H
#define LINKQUEUE_H
#include "queue.h"
#include "linklist.h"
namespace dataStructure
{
template<typename T>
class LinkQueue:public Queue<T>
{
public:
LinkQueue();
~LinkQueue();
int Length()const;
bool Empty() const;
void Clear();
void Traverse(void(*visit)(T &t))const;
bool OutQueue(T &t);
bool GetHead(T &t);
bool InQueue(const T &t);
private:
List<T>* list;
};
template<typename T>
LinkQueue<T>::LinkQueue()
{
list = new LinkList<T>;
}

template<typename T>
LinkQueue<T>::~LinkQueue()
{
if(list)
delete lisst;
}

template<typename T>
int LinkQueue<T>::Length() const
{
return list->Length();
}

template<typename T>
bool LinkQueue<T>::Empty() const
{
return list->Empty();
}

template<typename T>
void LinkQueue<T>::Clear()
{
list->Clear();
}

template<typename T>
void LinkQueue<T>::Traverse(void(*visit)(T &t))const
{
list->Traverse(visit);
}

template<typename T>
bool LinkQueue<T>::OutQueue(T &t)
{
if (list->Length() > 0)
{
return list->Delete(0, t);
}
return false;
}

template<typename T>
bool LinkQueue<T>::GetHead(T &t)
{
if (list->Length() > 0)
{
list->GetElem(0, t);
return true;
}
return false;
}

template<typename T>
bool LinkQueue<T>::InQueue(const T &t)
{
list->Add(t);
return true;
}

}
#endif
在main函数中对数据结构的定义进行测试
#include "stdafx.h"
#include "arrayqueue.h"
#include "linkqueue.h"
#include <iostream>
using namespace std;
using namespace dataStructure;
void visit(int &t)
{
cout << t << ",";
}
int main()
{
Queue<int> *queue = new LinkQueue<int>;
queue->InQueue(1);
queue->InQueue(2);
queue->InQueue(3);
queue->Traverse(visit);
cout << endl;
int i;
cout << queue->GetHead(i) << endl;
cout << i << endl;
cout << queue->OutQueue(i) << endl;
cout << i << endl;
queue->Traverse(visit);
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: