栈和队列
栈和队列:是在程序设计中被广泛使用的两种线性数据结构*,他们的特点在于基本操作的特殊性
栈:先进后出---出栈的时候,最后进栈的元素最先被压出栈来,就是说的
队列:先进先出---最先出队列的元素是最开始进去的元素
和线性表相比,他们的插入和删除操作受更多的约束和限定,故又称为限定性的线性表结构
模板不能直接使用
.h头文件里面不允许有内存的定义
一、模拟栈和队列
struct node
{
int id;
node* next;
};
//模拟栈
int arr[10] = {};
int len = 0;
int* p = arr;
for (int i = 0; i < 10; i++)
{
arr[len++] = i + 1;
}
len--;//出栈,数据在内存中还是存在,但是通过数组访问不到
for (int i = 0; i < len; i++)
{
printf("%d
", arr[i]);
}
//模拟队列
int arr1[10] = {};
int length = 0;
//入队(队尾)
for (int i = 0; i < 10; i++)
{
arr1[length++] = i + 1;
}
//出队(队头)
for (int i = 0; i < length-1; i++)
{
arr[i] = arr[i + 1];
}
length--;
node* head = NULL;
node* pcurrent = NULL;
//入栈
for (int i = 0; i < 10; i++)
{
pcurrent = new node;
pcurrent->id = i + 1;
pcurrent->next = head;
head = pcurrent;//将节点相连
}
//出栈
//pcurrent = head;
//head = head->next;
//delete pcurrent;//将头节点释放掉
pcurrent = head;
while (pcurrent)
{
printf("%d ", pcurrent->id);
pcurrent = pcurrent->next;
}
二、链式栈
struct node
{
int id;
node* next;
};
//链式栈,先进后出
node* head = NULL;
node* pcurrent = NULL;
for (int i = 0; i < 10; i++)
{
pcurrent = new node;
pcurrent->id = (i + 1) * 10;
pcurrent -> next = head;
head = pcurrent;
}
for (int i = 0; i < 10; i++)
{
pcurrent = head;
head = head->next;//移动头指针到下一个节点
delete pcurrent;
}
三、链式队
//链式队
node* head = NULL;
node* pcurrent = NULL;
//入队
for (int i = 0; i < 10; i++)
{
if (head == NULL)
{
head = new node;
head->id = i + 1;
head->next = NULL;
pcurrent=head;
}
else
{
pcurrent->next = new node;
pcurrent->next->id = i + 1;
pcurrent->next->next = NULL;
pcurrent = pcurrent->next;
}
}
//出队,先进先出
pcurrent = head;
head = head->next;//移动头指针指向下一个节点
delete pcurrent;//释放头节点
四、模板实现顺序栈
mystack.h
#pragma once
#include<iostream>
template<class T>
class cmystack//顺序栈
{
T *pbuff;//用来表示动态数组
size_t len;//动态数组的当前长度,也是当前的元素位置
size_t maxsize;//栈的最大长度
public:
cmystack();
//cmystack(cmystack const &other);//拷贝构造
void clear();//普通函数成员可以调用多次
~cmystack();
void push(T const &data);//入栈
void pop();//出栈,没有数据弹出,所以没有返回值
bool empty()const;//判断动态数组是否为空
T gettop() const;//得到栈顶元素
private:
void copystack();//内存重分配
};
template<class T>
cmystack<T>::cmystack()//定义构造函数,初始化数据
{
pbuff = NULL;
len = maxsize = 0;
}
template<class T>
void cmystack<T>::copystack()//内存重分配
{
if (len >= maxsize)
{
maxsize = maxsize + ((maxsize >> 1) > 1 ?( maxsize >> 1 ): 1);//1 2 3 4 6 9 13 19这样来扩容
T* temp = new T[maxsize];//new了maxsize个T大小的内存,他们的地址是连续的
for (size_t i = 0; i < len; i++)
{
temp[i] = pbuff[i];//将pubff里面的数据拷贝到新申请的内存中
}//相当于以前的动态数组的memcpy()内存拷贝
if (pbuff)
{
delete[]pbuff;
}
pbuff = temp;//指针pbuff再指向新申请的内存的地址,temp就是一个中间的指针
}
}
template<class T>
void cmystack<T>::push(T const &data)//入栈
{
copystack();
//内存重分配
pbuff[len++] = data;//数据入栈
}
template<class T>
void cmystack<T>::pop()//出栈
{
len--;//因为栈是先进后出的,所以len--就让数组访问不到最后填进去的数据了
}
template<class T>
bool cmystack<T>::empty() const//判断数组是否为空
{
return len == 0;//数组为空,返回true,数组不为空,返回false
}
template<class T>
T cmystack<T>::gettop() const//得到栈顶的元素
{
//因为len是数组中元素的个数,通过数组访问的时候len-1才是最后一个元素的位置
return pbuff[len - 1];//如果栈非空,逻辑没有问题,如果栈为空,则有问题
}
template<class T>
void cmystack<T>::clear()//释放内存
{
if (pbuff)
{
delete[]pbuff;
}
pbuff = NULL;
len = maxsize = 0;
}
template<class T>
cmystack<T>::~cmystack()//定义析构函数
{
clear();
}
五、模拟实现顺序队列
和顺序栈的区别就在于,数据出去的方式有点不同,
void pop();//出队,不用返回值,因为没有弹出数据
#pragma once
#include<iostream>
template<class T>
class cmyqueue
{
T* buff;//表示动态数组
int len;//动态数组的长度
int maxsize;//动态数组的最大容量
public:
cmyqueue();//构造函数
~cmyqueue();//析构函数
void clear();//用来释放指针
void push(T const&data);//入队
void pop();//出队,不用返回值,因为没有弹出数据
bool empty()const;//判断动态数组是否为空
T getqueue();//得到队列尾部元素
private:
void copyqueue();//扩大内存
};
template<class T>
cmyqueue<T>::cmyqueue()
{
buff = NULL;
len = maxsize = 0;
}
template<class T>
cmyqueue<T>::~cmyqueue()
{
clear();
}
template<class T>
void cmyqueue<T>::clear()
{
if (buff)
{
delete[]buff;
}
buff = NULL;
len = maxsize = 0;
}
template<class T>
void cmyqueue<T>::push(T const & data)
{
//插入数据前先判断有没有足够的内存空间,没有就申请
copyqueue();
//现在开始插入数据
buff[len++] = data;//一个一个数据的进行插入
}
template<class T>
void cmyqueue<T>::pop()
{
for (int i = 0; i < len - 1; i++)
{
buff[i] = buff[i + 1];
}
len--;
}
template<class T>
bool cmyqueue<T>::empty() const
{
return len == 0;
}
template<class T>
T cmyqueue<T>::getqueue()
{
return buff[0];
}
template<class T>
void cmyqueue<T>::copyqueue()
{
if (len >= maxsize)
{
maxsize = maxsize + ((maxsize >> 1) > 1 ? maxsize >> 1 : 1);//改写动态数组的最大下标
T* temp = new T[maxsize];//这个才是扩容的操作
for (int i = 0; i < len; i++)
{
temp[i] = buff[i];//将原来的动态数组中的数据拷贝到新申请的内存中
}
if (buff)
{
delete[]buff;
}
buff = temp;//再让原来的指针指向新的内存地址
}
}
六、模板实现链式栈
mystack_list.h
#pragma once
#include<iostream>
template<class T>
class cmystack_list
{
struct node
{
int id;
node* next;
};
node* head;//链表头指针
public:
cmystack_list();//构造函数
~cmystack_list();//析构函数
void clear();//释放内存
void headpush(T const &data);//头插法入栈
void endpush(T const &data);//尾插法入栈
T headgettop();//得到栈顶的元素
T endgettop();
void headpop();//出栈
void endpop();//出栈
};
template<class T>
cmystack_list<T>::cmystack_list()
{
head = NULL;
}
template<class T>
cmystack_list<T>::~cmystack_list()
{
clear();
}
template<class T>
void cmystack_list<T>::clear()
{
node* temp = NULL;
while (head)
{
temp = head;
head = head->next;
delete[] temp;
}
}
template<class T>
void cmystack_list<T>::headpush(T const & data)//头插法,从链表的头节点插入
{
node* ptemp = new node;
ptemp->id = data;
ptemp->next = head;
head = ptemp;
}
template<class T>
void cmystack_list<T>::endpush(T const & data)
{
node* pend = head;
node* ptemp = new node;
ptemp->id = data;
ptemp->next = NULL;
if (head == NULL)
{
head = ptemp;
}
else
{
while (pend->next)
{
pend = pend->next;
}
pend->next = ptemp;
}
}
template<class T>
T cmystack_list<T>::headgettop()
{
return head->id;
}
template<class T>
T cmystack_list<T>::endgettop()
{
node* ptemp = head;
while (ptemp->next)
{
ptemp = ptemp->next;
}
return ptemp->id;
}
template<class T>
void cmystack_list<T>::headpop()
{
//因为用的是头插法,头指针指的就是最后插入的数据,这个数据要最先被弹出来5
node* ptemp = head;
head = head->next;
delete[]ptemp;
}
template<class T>
void cmystack_list<T>::endpop()
{
if (head == NULL)
return;
if (head->next == NULL)
{
delete head;
head = NULL;
return;
}
node* pcurrent = head;
while (pcurrent->next)
{
if (pcurrent->next->next == NULL)
break;
pcurrent = pcurrent->next;
}
delete pcurrent->next;
pcurrent->next = NULL;
}
七、模板实现链式队列
myqueue_list.h
#pragma once
#include<iostream>
template<class T>
class cmyqueue_list
{
struct node
{
int id;
node* next;
};
node* head;
public:
cmyqueue_list();
~cmyqueue_list();
void clear();
void headpush(T const &data);
void headpop();
T endgetfirst();
T headgetfirst();
void endpush(T const &data);
void endpop();
};
template<class T>
cmyqueue_list<T>::cmyqueue_list()
{
head = NULL;
}
template<class T>
cmyqueue_list<T>::~cmyqueue_list()
{
clear();
}
template<class T>
void cmyqueue_list<T>::clear()
{
node* ptemp = NULL;
while (head)
{
ptemp = head;
head = head->next;
delete[]ptemp;
}
}
template<class T>
void cmyqueue_list<T>::headpush(T const & data)
{
node* ptemp = new node;
ptemp->id = data;
ptemp->next = head;
head = ptemp;
}
template<class T>
void cmyqueue_list<T>::headpop()
{
if (head == NULL)
return;
if (head->next == NULL)
{
delete head;
head = NULL;
return;
}
node* ptemp = head;
while (ptemp->next)
{
if (ptemp->next->next == NULL)
break;
ptemp = ptemp->next;
}
delete ptemp->next;
ptemp->next = NULL;
}
template<class T>
T cmyqueue_list<T>::endgetfirst()
{
return head->id;
}
template<class T>
T cmyqueue_list<T>::headgetfirst()
{
node* ptemp = head;
while (ptemp->next)
{
ptemp = ptemp->next;
}
return ptemp->id;
}
template<class T>
void cmyqueue_list<T>::endpush(T const & data)
{
node* ptemp = new node;
ptemp->id = data;
ptemp->next = NULL;
if (head == NULL)
{
head = ptemp;
}
else
{
node* pcurrent = head;
while (pcurrent->next)
{
pcurrent = pcurrent->next;
}
pcurrent->next = ptemp;
}
}
template<class T>
void cmyqueue_list<T>::endpop()
{
node* ptemp = head;
head = head->next;
delete ptemp;
}
八、使用前面的所写头文件
main.cpp
#include<iostream>
#include"mystack.h"
using namespace std;
int main()
{
cmystack<int> ms;
for (int i = 0; i < 10; i++)
{
ms.push(i + 1);
}
for (int i = 0; i < 12; i++)
{
if (!ms.empty())//先判断数组是否为空
{
printf("%d
", ms.gettop());
ms.pop();//每次出栈
}
}
return 0;
}