数据结构的三要素:
- 逻辑结构;
- 元素的运算;
- 存储结构;
栈 (stack)
定义:
线性表分为两种,一种是顺序表,一种是链表。而栈也可以理解为一种特殊的线性表;
栈只允许在一段进行数据的插入或者删除操作,也就是数据是后进先出;
基本操作
InitStack();
初始化一个栈,分配内存空间;DestoryStack(&S);
销毁一个栈,释放内存空间;Push(&s, value);
若栈未满则向栈顶压入元素value;Pop(&s, output);
若栈非空,则弹出栈顶元素并用output接收;GetTop(&s, output);
若栈非空,则读取栈顶元素并用output接收;bool StackEmpty(s);
判断栈是否为空;
顺序栈的实现与操作
cpp
#include <iostream>
using namespace std;
template <class T>
struct Node
{
//记录栈底的地址
T* pos;
//记录栈顶元素的相对位置
int top;
};
template<class T>
class MyStack
{
private:
Node<T> d;
//记录栈的最大容量
int capacity;
public:
MyStack()
{
capacity = 10;
d.top = -1;
d.pos = new T[capacity];
}
MyStack(int n)
{
capacity = n;
d.top = -1;
d.pos = new T[capacity];
}
bool StackEmpty()
{
return d.top == -1;
}
void Push(T value)
{
if (d.top != capacity - 1)
{
d.pos[++d.top] = value;
}
else
{
cout << "栈已满" << endl;
exit(0);
}
}
void Pop(T &output)
{
if (!StackEmpty())
{
output = d.pos[d.top--];
}
else
{
cout << "栈已空" << endl;
}
}
void GetTop(T &output)
{
if (!StackEmpty())
{
output = d.pos[d.top];
}
else
{
cout << "栈已空" << endl;
}
}
~MyStack()
{
delete[] d.pos;
d.pos = NULL;
}
};
void test()
{
MyStack<int> s;
int n = 0;
s.Push(10);
if (!s.StackEmpty())
{
cout << "栈非空" << endl;
}
s.GetTop(n);
cout << n << endl;
s.Pop(n);
if (s.StackEmpty())
{
cout << "成功弹出" << endl;
}
}
int main()
{
test();
return 0;
}
共享栈
由于顺序栈的存储空间相对固定,所以在使用时会有一定的不便:如果开始分配的内存小了可能会出现内存不够用的问题,如果一开始就分配很大的内存又会有空间浪费的问题,这时候用共享栈就可以很好的解决这个问题;
顾名思义,共享栈就是两个栈公用一块内存,但是两个栈的top在最开始分别指向这块内存的两端,并以此为起点压入数据。
需要注意的是 使用共享栈时一定要注意内存是否用完,否则可能出现越界访问的问题;
链式栈的实现
链式栈本质可以看作是一个单链表,只是限制了结点的增删操作只能在链表的一端进行;
队列
定义
队列同样是一个操作受限的线性表,队列只允许在一段进行插入,在另一端进行删除;
允许插入的一段叫做队尾,允许删除的一段叫做对头;
基本操作
队列的基本操作同样是创 销 增 删 查;
Init()
Destory()
Push()
Pop()
GetHead()
Empty()
队列的实现与操作
cpp
#include <iostream>
using namespace std;
template<class T>
struct Node
{
T data;
Node* next;
Node(T value)
{
data = value;
next = NULL;
}
~Node()
{
next = NULL;
}
};
template <class T>
class MyQueue
{
private:
Node<T>* n;
Node<T>* Head;
Node<T>* Tail;
public:
MyQueue()
{
Head = NULL;
Tail = NULL;
}
MyQueue(T value)
{
n = new Node(value);
n->data = value;
n->next = NULL;
Head = &n;
Tail = &n;
}
~MyQueue()
{
Node<T>* temp = Head;
while (Head)
{
Head = Head->next;
delete temp;
temp = Head;
}
}
bool Empty()
{
return Tail == NULL && Head == NULL;
}
void Push(T value)
{
if (Empty())
{
n = new Node<T>(value);
Head = n;
Tail = n;
}
else
{
Tail->next = new Node<T>(value);
Tail = Tail->next;
Tail->next = NULL;
}
}
void Pop()
{
if (Empty())
{
cout << "队列已空" << endl;
exit(0);
}
else if (Tail == Head)
{
delete Tail;
Tail = NULL;
Head = NULL;
}
else
{
Node<T>* temp = Head;
Head = Head->next;
delete temp;
temp = NULL;
}
}
T GetTop()
{
if (Empty())
{
cout << "队列已空" << endl;
exit(0);
}
else
{
return Head->data;
}
}
};
void test()
{
MyQueue<int> q;
q.Push(1);
q.Push(2);
q.Push(3);
while (!q.Empty())
{
cout << q.GetTop() << endl;
q.Pop();
}
}
int main()
{
test();
return 0;
}
总结
- 栈和队列都是增删操作受限制的特殊线性表;
- 栈和队列的物理结构可以是连续的也可以是不连续的;
- 另外,栈和队列的元素都是不能自由访问的。栈只能访问栈顶的元素,队列只能访问对头的元素;