• 栈和队列


    栈和队列

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

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

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

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

    模板不能直接使用

    .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;
    }
    
  • 相关阅读:
    Java程序运行机制及开发环境
    Redis源码分析(八)--- t_hash哈希转换
    Redis源码分析(八)--- t_hash哈希转换
    Redis源码分析(八)--- t_hash哈希转换
    Redis源码分析(九)--- t_list,t_string的分析
    Redis源码分析(九)--- t_list,t_string的分析
    Redis源码分析(九)--- t_list,t_string的分析
    Redis源码分析(十)--- testhelp.h小型测试框架和redis-check-aof.c日志检测
    Redis源码分析(十)--- testhelp.h小型测试框架和redis-check-aof.c日志检测
    Redis源码分析(十)--- testhelp.h小型测试框架和redis-check-aof.c日志检测
  • 原文地址:https://www.cnblogs.com/Kissfly123/p/14523162.html
Copyright © 2020-2023  润新知