栈:
栈是一种操作受限的线性表只允许从一端插入和删除数据。栈有两种存储方式,即线性存储(顺序栈)和链表存储(链栈)。栈的一个最重要的特征就是栈的插入和删除只能在栈顶进行,所以每次删除的元素都是最后进栈的元素,故栈也被称为后进先出(LIFO)表。每个栈都有一个栈顶指针,它初始值为-1,且总是指向最后一个入栈的元素,栈有两种处理方式,即进栈(push)和出栈(pop),因为在进栈只需要移动一个变量存储空间,所以它的时间复杂度为O(1),但是对于出栈分两种情况,栈未满时,时间复杂度也为O(1),但是当栈满时,需要重新分配内存,并移动栈内所有数据,所以此时的时间复杂度为O(n)。以下举例栈结构的两种实现方式,线性存储和链接存储。
1. 顺序栈的实现
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
template<class datatype>
class StackList
{
private:
datatype *base;//栈底指针
datatype *top;//栈顶指针
int maxsize;//最大容量
int len;//栈元素个数
public:
StackList();//不带参数的构造函数
StackList(int n);//初始化最大容量为n的构造函数
~StackList();//析构函数
void push(datatype value);//入栈
void pop();//出栈
datatype gettop();//获取栈顶元素
datatype getbase();//获取栈底元素
bool isequal(const StackList & A);//判断两个栈是否相等
friend ostream &operator<<(ostream &output, const StackList &D)
{
if (D.len == 0)
{
cout << "stack is empty" << endl;
}
else
{
datatype *p = D.base;
for (int i = 0; i < D.len; i++)
{
output << *p << " ";
p++;
}
cout << endl;
}
return output;
}
};
//不带参数的构造函数
template<class datatype>
StackList<datatype>::StackList()
{
len = 0;
maxsize = 10;
base = new datatype[maxsize];
if (!base)
cerr << "存储分配失败" << endl;
top = base;
}
//初始化最大容量为n的构造函数
template<class datatype>
StackList<datatype>::StackList(int n)
{
len = 0;
maxsize = n;
base = new datatype[maxsize];
if (!base)
cerr << "存储分配失败" << endl;
top = base;
}
//析构函数
template<class datatype>
StackList<datatype>::~StackList()
{
delete base;
}
//入栈
template<class datatype>
void StackList<datatype>::push(datatype value)
{
if (top - base == maxsize)
cerr << "存储空间已满" << endl;
else
{
*top++ = value;
len++;
}
}
//出栈
template<class datatype>
void StackList<datatype>::pop()
{
if (base == top)
cerr << "stack is empty ,can't pop" << endl;
else
{
top--;
len--;
}
}
//获取栈顶元素
template<class datatype>
datatype StackList<datatype>::gettop()
{
return *(top - 1);
}
//获取栈底元素
template<class datatype>
datatype StackList<datatype>::getbase()
{
return *base;
}
//判断两个栈是否相等
template<class datatype>
bool StackList<datatype>::isequal(const StackList & A)
{
if (len != A.len)
return false;
else
{
datatype *q = base;
datatype *k = A.base;
for (int i = 0; i < len; i++)
{
if (*q != *k)
return false;
else
{
q++;
k++;
}
}
return true;
}
}
int main()
{
//测试
StackList<int> A;
StackList<int> B(5);
A.push(1);
A.push(2);
cout << A;
A.pop();
A.push(3);
cout << A;
cout << A.gettop() << endl;
cout << A.getbase() << endl;
cout << A.isequal(B) << endl;
system("pause");
return 0;
}
2. 链栈的实现:
#include<iostream>
using namespace std;
template<class datatype>
class LinkStack;
template<class datatype>
class node
{
public:
friend class LinkStack<datatype>;
datatype val;
node<datatype> *next;
node(datatype x) : val(x), next(NULL) {};
};
template<class datatype>
class LinkStack
{
private:
node<datatype> *S;
int len;
public:
LinkStack();
LinkStack(datatype a[],int n);//将数组a的前n个元素压入栈
~LinkStack();
void push(datatype value);//入栈
void pop();//出栈
datatype top();//获取栈顶元素
bool empty1();//判空
bool empty2();//判空
friend ostream &operator<<(ostream &output, const LinkStack &D)
{
if (D.len==0)
{
cout << "LinkStack is empty" << endl;
}
else
{
node<datatype> *p = D.S;
for (int i = 0; i < D.len; i++)
{
cout << p->val << " ";
p = p->next;
}
cout << endl;
}
return output;
}
};
template<class datatype>
LinkStack<datatype>::LinkStack()
{
S = NULL;
len = 0;
}
template<class datatype>
LinkStack<datatype>::LinkStack(datatype a[],int n)
{
S = NULL;
int i = 0;
for (; i < n; i++)
{
if (a[i] != 0)
push(a[i]);
else break;
}
len = i ;
}
template<class datatype>
LinkStack<datatype>::~LinkStack()
{
if (len != 0)
{
node<datatype> *p = S,*k;
for (int i = 0; i < len; i++)
{
k = p->next;
delete p;
p = k;
}
}
}
template<class datatype>
void LinkStack<datatype>::push(datatype value)
{
node<datatype> *p=S;
S = new node<datatype>(value);
S->next = p;
len++;
}
template<class datatype>
void LinkStack<datatype>::pop()
{
node<datatype> *p = S;
S = S->next;
len--;
delete p;
}
template<class datatype>
datatype LinkStack<datatype>::top()
{
return S->val;
}
template<class datatype>
bool LinkStack<datatype>::empty1()
{
return !len;
}
template<class datatype>
bool LinkStack<datatype>::empty2()
{
if (S == NULL)
return true;
else return false;
}
int main()
{
//测试
int a[10] = { 1,3,4,2 };
LinkStack<int> A;
LinkStack<int> B(a,5);
cout << B;
//cout << A.empty1() << " " <<A.empty2() << endl;
A.push(1);
//cout << A.empty1() << " " << A.empty2() << endl;
A.push(2);
cout << A;
A.pop();
cout << A;
cout << A.top()<<endl;
system("pause");
return 0;
}
队列:
队列以一种先入先出(FIFO)的线性表,教科书上有明确的定义与描述。类似于现实中排队时的队列(队尾进,队头出),队列只在线性表两端进行操作,插入元素的一端称为表尾,删除(取出)元素的一端称为表头。分别对应于入队和出队操作。队列有两种存储方式,即线性存储(循环队列)和链表存储(链队)
1. 循环队列的实现:
#include<iostream>
using namespace std;
//弃用一个空间的循环队列,防止假溢出
template<class datatype>
class Cirqueue
{
private:
int front;
int rear;
datatype *base;
int maxsize;
public:
Cirqueue();
Cirqueue(int max);
~Cirqueue();
bool empty();
bool full();
int getlength();
void enqueue(datatype value);
void dequeue();
datatype getfront();
datatype getrear();
friend ostream &operator<<(ostream &output, Cirqueue& D)
{
if (D.empty())
cout << "队列为空" << endl;
else
{
int p = D.front;
for (int i = 0; i < D.getlength(); i++)
{
output << D.base[p] << " ";
p = (p + 1) % D.maxsize;
}
cout << endl;
}
return output;
}
};
template<class datatype>
Cirqueue<datatype>::Cirqueue()
{
maxsize = 11;
base = new datatype[maxsize];
front = rear =0;
}
template<class datatype>
Cirqueue<datatype>::Cirqueue(int max)
{
maxsize = max+1;
base = new datatype[maxsize];
front = rear = 0;
}
template<class datatype>
Cirqueue<datatype>::~Cirqueue()
{
delete base;
}
template<class datatype>
bool Cirqueue<datatype>::empty()
{
return front == rear;
}
template<class datatype>
bool Cirqueue<datatype>::full()
{
return (rear + 1) % maxsize == front;
}
template<class datatype>
int Cirqueue<datatype>::getlength()
{
return (rear - front + maxsize) % maxsize;
}
template<class datatype>
void Cirqueue<datatype>::enqueue(datatype value)
{
if (full())
cout << "队列已满" << endl;
else
{
base[rear] = value;
rear++;
}
}
template<class datatype>
void Cirqueue<datatype>::dequeue()
{
if (empty())
cout << "队列为空" << endl;
else
front = (front + 1) % maxsize;
}
template<class datatype>
datatype Cirqueue<datatype>::getfront()
{
return base[front];
}
template<class datatype>
datatype Cirqueue<datatype>::getrear()
{
return base[rear-1];
}
int main()
{
//test
Cirqueue<int> A(3);
A.enqueue(1);
A.enqueue(2);
A.dequeue();
A.enqueue(4);
A.enqueue(4);
cout << A;
cout << A.getlength() << " " << A.getfront() <<" "<<A.getrear()<< endl;
system("pause");
return 0;
}
2.链队的实现:
#include<iostream>
using namespace std;
template<class datatype>
class Linkqueue;
template<class datatype>
class node
{
public:
//friend class Linkqueue<datatype>;
datatype data;
node<datatype> *next;
node(datatype x) : data(x), next(NULL) {};
};
template<class datatype>
class Linkqueue
{
private:
node<datatype> *front;
node<datatype> *rear;
int len;
public:
Linkqueue();
~Linkqueue();
void inqueue(datatype val);
void dequeue();
int getlen1();
int getlen2();
datatype getfront()
{
return front->next->data;
}
datatype getrear()
{
return rear->data;
}
friend ostream &operator<<(ostream &output, const Linkqueue &D)
{
if (D.len == 0)
{
cout << "Linkqueue is empty" << endl;
}
else
{
node<datatype> *p = D.front->next;
for (int i = 0; i < D.len; i++)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
return output;
}
};
template<class datatype>
Linkqueue<datatype>::Linkqueue()
{
front = new node<datatype>(-1);
rear = front;
front->next = NULL;
len = 0;
}
template<class datatype>
Linkqueue<datatype>::~Linkqueue()
{
while (rear != front)
{
node<datatype> *temp = front->next;
delete front;
front = temp;
}
delete rear;
}
template<class datatype>
void Linkqueue<datatype>::inqueue(datatype val)
{
rear->next = new node<datatype>(val);
rear = rear->next;
len++;
}
template<class datatype>
void Linkqueue<datatype>::dequeue()
{
if (len == 0)
{
cerr << "Linkqueue is empty,can't dequeue" << endl;
}
else
{
node<datatype> *temp = front->next;
front->next = front->next->next;
delete temp;
len--;
}
}
template<class datatype>
int Linkqueue<datatype>::getlen1()
{
return len;
}
template<class datatype>
int Linkqueue<datatype>::getlen2()
{
node<datatype> *temp = front;
int count = 0;
while (temp != rear)
{
count++;
temp = temp->next;
}
return count;
}
int main()
{
//test
Linkqueue<int> A;
A.inqueue(3);
A.inqueue(2);
A.inqueue(1);
A.inqueue(4);
cout << A;
cout << A.getlen2() << endl;
cout << A.getfront() << " " << A.getrear() << endl;
A.dequeue();
A.dequeue();
A.dequeue();
cout << A;
system("pause");
return 0;
}
栈和队列的区别:
- 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
- 栈是先进后出,队列是先进先出。
- 栈只允许在表尾一端进行插入和删除,队列只允许在表尾一端进行插入,在表头一端进行删除。