栈和队列

栈和队列

栈和队列:是在程序设计中被广泛使用的两种线性数据结构*,他们的特点在于基本操作的特殊性

:先进后出---出栈的时候,最后进栈的元素最先被压出栈来,就是说的

队列:先进先出---最先出队列的元素是最开始进去的元素

和线性表相比,他们的插入和删除操作受更多的约束和限定,故又称为限定性的线性表结构

模板不能直接使用

.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\n", 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\n", ms.gettop());
			ms.pop();//每次出栈
		}
	}  
    
    
    return 0;
}
posted @ 2021-03-12 12:28  kisfly  阅读(38)  评论(0编辑  收藏  举报