/***********************************************************************/
/*队列和栈一样也是一个受限线性表 ,栈要求的是在同一端进行插入和删除操作*/
/*而队列,它要求在一端进行插入(入队),另一端进行删除(出队的操作)   */
/*我们把允许入队操作的一端称为队尾,把允许出队列的一端称为队首         */
/*栈是一个后进先出的结构,而队列则是一个先进先出的数据结构             */
/*任何数据结构都可以有链式存储和数组存储两种存储结构                   */
/*本次采用的实现方式是数组实现,队列寻找元素的方式也有三种             */
/*第一种:将第i个元素放在i位置,但是这样虽然能够很的利用空间           */
/*但是删除的时间复杂度将会是O(n),因为每删除一个圆度都要将首元素后面的 */
/*元素向前移动n-1次(n是队列的大小),所以删除的时间复杂度为O(n)       */
/*这种方式暗示我们始终把数组的最左端视为队列的首部                     */
/*而将数组的右端size - 1位置视为队列的尾部(size为队列的长度)         */
/*其队列的大小就是 队尾索引值 + 1                                      */
/*第二种方式:队列的首部是数组左边的一个游标,每次删除操作都动态更新   */
/*初始话的时候它指向一个无效位置                                       */
/*队列的尾部是数组右边的一个游标,每次插入都动态更新它,初始化时指向   */
/*一个无效位置                                                         */
/*所以元素的定位公式是 location(i) = location(0) (队首元素的位置)+ i  */
/*队列的大小是: 队尾索引 - 队首索引 +1                                 */
/*使用这种方式,我们需要一个3元组才能描述这个队列,即                  */
/*(队首位置,队尾位置,存储元素的一维数组)                            */
/*其ADT大致如下:                                                      */
/* class ArrayQueue                                                    */
/* {* public:*     int size() const*     {*         if( -1 = m_iBack )*         {*              return 0;*         }*         return m_iBack - m_iFront +1;*     }*     int empty() const*     {*         if( -1 == m_iBack || m_iFront > m_iBack)  //在连续删除不插入的时候就有可能出现 m_iFront > m_iBack的时候*              return true;*         return false;*     }*     void pop()               //删除队首元素*     {*         if(true == empty())*              return;*         else*         {*              m_pArray[m_iFront].~T();*              ++m_iFront;             //将数组的左端当做队列首部,这样能使得插入和删除的时间复杂度都是O(1)*         }*     }*     void push()*     {*         //将数组的右端视为队列的尾部*         if( m_iBack  >= m_iMaxSize-1 )                       //说明此队列已经满了*         {*              return;                 //其实应该是扩大数组容量, 迁移元素,但是这个类要讨论的不是这种实现方式,或者将队列整体左移*         }*         ++m_iBack;*         m_pArray[m_iBack] = T;*      }* private:*     int m_iMaxSize{100};             //队列的最大大小*     int m_iFront{ -1 };              //队首元素的索引*     int m_iBack{ -1 };               //队尾元素的索引*     T *m_pArray{nullptr};* }* 通过上面的简单实现,可以看出一个问题,当逐步执行删除操作时,会造成较大的空间浪费    */
/*方式三:循环队列,就是将一维数组首尾相连视为一个环,每个元素的位置由公式             */
/*现在队列是一个环形,那么意味着每一个元素都有其下一个位置和前一个位,此时确定第i个    */
/*元素的位置,使用公式:location(i) = (location(0)(队首元素的位置) + i ) % arrayLength */
/*公式中arrayLength是你为这个队列分配的一维数组的大小,而location(0)则是队首元素的位置 */
/*由公式可知要知道第i个元素的位置,必须要知道第0个元素的位置,假定和队首元素位置相关的 */
/*变量其名字为queueFront,现在我们约定,queueFront指向的不是队首元素,而是沿逆时针方向 */
/*指向队首元素的下一位置                                                               */
/*另外,依然使用一个变量来记录队尾元素的位置,假设名字为queueBack,它直接指向队尾元素  */
/***************************************************************************************/#ifndef ARRAYQUEUE_H_
#define ARRAYQUEUE_H_
//本例中使用环形数组来描述这个队列
#include <stdexcept>
#include <cmath>
#include <new>
#include <algorithm>
template <typename T>
class ArrayQueue
{
public:bool empty() const{//这个判断条件意味着,在这个数组中,我们永远留着一个空位,确保m_iTheFront和m_iTheRear除了初始情况之外,永远不会存在相等的情况//所以在每一次的插入操作之前,都需要先判断一下本次操作会不会让队列变满,如果会,那么就扩充数组容量,然后再执行插入操作,//按照这种策略,队列中的元素个数最多只能是 m_iArraySize - 1if(m_iTheFront == m_iTheRear)return true;return false;}void push(const T &element);        //在队尾插入元素void pop();                         //在队首删除元素T& front();                         //返回队首元素T& back();                          //返回队尾元素int size() const;                           //返回队列中元素的个数int maxsize() const;                        //返回队列能容纳的最大元素个数
    ArrayQueue();~ArrayQueue();
private:int m_iTheFront{0}; //指向队列首元素的游标,重要,初始情况下,m_iTheFront和m_iTheRear的值都是0int m_iTheRear{0};          //指向队列尾元素的游标int m_iArraySize{10};T *m_pArray{nullptr};void expandCapacity();      //扩充一维数组的容量
};template <typename T>
void ArrayQueue<T>::push(const T &element)
{if( (m_iTheRear + 1) % m_iArraySize == m_iTheFront ){expandCapacity();//如果下一个插入位置刚好和首元素逆时针方向上的下一位置游标相等,说明这个队列已经满了
   }m_iTheRear = (m_iTheRear + 1) % m_iArraySize;m_pArray[m_iTheRear] = element;
}template <typename T>
void ArrayQueue<T>::pop()
{if(true == empty())return;m_iTheFront = (m_iTheFront + 1) % m_iArraySize;m_pArray[m_iTheFront].~T();
}template <typename T>
T& ArrayQueue<T>::front()
{if(true == empty())throw std::runtime_error("Empty Queue");//先计算出队列首元素的位置,然后返回它的值return m_pArray[(m_iTheFront + 1) % m_iArraySize];
}template <typename T>
T& ArrayQueue<T>::back()
{//返回队列的尾部元素,m_iTheRear这个游标直接指向队尾元素if(true == empty())throw std::runtime_error("Empty Queue");return m_pArray[m_iTheRear];
}template <typename T>
int ArrayQueue<T>::size() const
{//循环队列的大小计算分为两种情况//情形一:m_iTheFront < m_iTheRear,那么队列的大小就是 m_iTheRear - m_iTheFront//情形二:m_iTheFront > m_iTheRear,那么计算起来就分为两部分了,一部分是 0 + m_iTheRear,另一部分是 m_iArraySize - m_iTheFront,所以合起来就是//m_iTheRear + m_iArraySize - m_iTheFront//把上述两种情况合在一起,那么计算大小的公式就是  (m_iTheRear - m_iTheFront + m_iArraySize) % m_iArraySizereturn (m_iTheRear - m_iTheFront + m_iArraySize) % m_iArraySize;
}template <typename T>
int ArrayQueue<T>::maxsize() const
{return m_iArraySize - 1;    //数组中最多只能存储最大大小减去一个位置的元素
}template <typename T>
ArrayQueue<T>::ArrayQueue()
{//如果分配内存失败的话,会抛出一个bad_alloc的异常,记得使用时捕获它m_pArray = new T[m_iArraySize * sizeof(T)];
}template <typename T>
ArrayQueue<T>::~ArrayQueue()
{for(int i = 0; i < m_iArraySize; ++i){//析构函数,要把数组中的每一对象释放了,因为new的时候会调用默认构造函数,如果是使用了内存分配器allocate,那么要进行更加精细的操作m_pArray[i].~T();}if(nullptr != m_pArray){delete[] m_pArray;m_pArray;}
}template <typename T>
void ArrayQueue<T>::expandCapacity()
{//首先计算出队列首元素的在数组中所在的索引,现在我们把这个一维数组视为一个环形,这里的m_iTheFront指向的是自队列首元素结点处逆时针方向的下一位置//但是它本质上其实还是一个一维数组,一维数组它在内存中的索引从0开始,那么怎么判断目前的结构是不是形成了一个环呢?//只要m_iTheRear(尾元素游标)和 m_iTheFront(首元素处逆时针下一位置游标)都处于0以及0之后的索引,那么就认为它形成了一个环。//求出队列首元素实际的存储位置,因为我们是把一维数视为环形的,并且m_iTheFront是首元素逆时针方向的下一位置,将它想象成一个环,可以得到求首元素位置的公式为:// (m_iTheFront + 1) % m_iArraySize(数组大小),要对数组大小取模,是因为,你的环,每一个位置上的索引是固定的,不是无限增长的。int iStart = (m_iTheFront + 1) % m_iArraySize;              //队列首元素的位置索引T *newQueue = new (std::nothrow) T[2 * m_iArraySize];if(iStart < 2){//没有形成环std::copy(m_pArray + iStart , m_pArray + iStart + m_iArraySize - 1,newQueue);}else{//形成环std::copy(m_pArray+iStart,m_pArray+m_iArraySize,newQueue);std::copy(m_pArray,m_pArray + m_iTheRear + 1,newQueue + m_iArraySize - iStart);}//设置新的队列的首元素和尾元素的位置m_iTheFront = 2*m_iArraySize - 1;m_iTheRear = m_iArraySize - 2;      // 这里是m_iArraySize -2 ; -2 的原因是满队列的情况下还要留出一个位置,然后索引最大是m_iArraySize -2.综合起来就得到了-2这个结论m_iArraySize *= 2;delete [] m_pArray;m_pArray = newQueue;
}template <typename T>
class Node
{
public:Node() = default;Node(const T& element) : m_Element(element){};Node(const T& element,const Node<T> *pNext):m_Element(element),m_pNextNode(pNext) {};T m_Element;Node<T> *m_pNextNode{nullptr};
};template <typename T>
class LinkedQueue
{
public:bool empty() const{if(nullptr == m_pFront)return true;return false;}int size() const{return m_iSize;}T& front() const;           //返回队列的队首元素T& back() const;            //返回队列的队尾元素void push(const T& element);        //从队列的尾部插入元素void pop();                         //删除队列首部的元素LinkedQueue() = default;~LinkedQueue();
private:Node<T> *m_pFront{nullptr};                 //队列的首部int m_iSize{0};                             //队列大小Node<T> *m_pBack{nullptr};                  //队列的尾部void clear();                               //清理数据结构
};template <typename T>
T& LinkedQueue<T>::front() const
{if(false == empty())return m_pFront->m_Element;
}template <typename T>
T& LinkedQueue<T>::back() const
{if(false == empty())return m_pBack->m_Element;
}template <typename T>
void LinkedQueue<T>::push(const T &element)
{Node<T> *pNewNode = new(std::nothrow) Node<T>(element);if(nullptr == pNewNode)return;if(m_iSize == 0){//如果大小等于0,那么说明,这是第一个被插入链表的元素m_pFront = pNewNode;            //这时候时头指针指向新的结点
    }else{//队列不为空,此时链表的生成方向有两种,一种是从头部开始链接,另一种从尾部开始链接,当你写到pop函数的时候就能发现如果从尾部开始链接,删除会变的很复杂,因为我们的链表是单向的m_pBack->m_pNextNode = pNewNode;    //令新结点的指针域指向记录尾结点位置的m_pBack
    }m_pBack = pNewNode;                 //更新尾结点++m_iSize;
}template <typename T>
void LinkedQueue<T>::pop()
{if(true == empty())return;Node<T> *pTemp = m_pFront;          //保存一下队首元素的位置,这个待会要删除结点用m_pFront = pTemp->m_pNextNode;pTemp->m_Element.~T();              //销毁对象if(pTemp != nullptr){delete pTemp;pTemp = nullptr;}--m_iSize;if( 0 == m_iSize)m_pFront = m_pBack = nullptr;
}template <typename T>
void LinkedQueue<T>::clear()
{for(int i=0; i < m_iSize; ++i){Node<T> *pTempNode = m_pFront;m_pFront = pTempNode->m_pNextNode;if(nullptr != pTempNode){delete pTempNode;pTempNode = nullptr;}}m_pFront = m_pBack = nullptr;
}template <typename T>
LinkedQueue<T>::~LinkedQueue()
{clear();
}
#endif

  以上代码均在gcc4.8.5上跑过了。欢迎指正。

/***********************************************************************//*队列和栈一样也是一个受限线性表 ,栈要求的是在同一端进行插入和删除操作*//*而队列,它要求在一端进行插入(入队),另一端进行删除(出队的操作)   *//*我们把允许入队操作的一端称为队尾,把允许出队列的一端称为队首         *//*栈是一个后进先出的结构,而队列则是一个先进先出的数据结构             *//*任何数据结构都可以有链式存储和数组存储两种存储结构                   *//*本次采用的实现方式是数组实现,队列寻找元素的方式也有三种             *//*第一种:将第i个元素放在i位置,但是这样虽然能够很的利用空间           *//*但是删除的时间复杂度将会是O(n),因为每删除一个圆度都要将首元素后面的 *//*元素向前移动n-1次(n是队列的大小),所以删除的时间复杂度为O(n)       *//*这种方式暗示我们始终把数组的最左端视为队列的首部                     *//*而将数组的右端size - 1位置视为队列的尾部(size为队列的长度)         *//*其队列的大小就是 队尾索引值 + 1                                      *//*第二种方式:队列的首部是数组左边的一个游标,每次删除操作都动态更新   *//*初始话的时候它指向一个无效位置                                       *//*队列的尾部是数组右边的一个游标,每次插入都动态更新它,初始化时指向   *//*一个无效位置                                                         *//*所以元素的定位公式是 location(i) = location(0) (队首元素的位置)+ i  *//*队列的大小是: 队尾索引 - 队首索引 +1                                 *//*使用这种方式,我们需要一个3元组才能描述这个队列,即                  *//*(队首位置,队尾位置,存储元素的一维数组)                            *//*其ADT大致如下:                                                      *//* class ArrayQueue                                                    *//* { * public: *     int size() const *     { *         if( -1 = m_iBack ) *         { *              return 0; *         } *         return m_iBack - m_iFront +1; *     } *     int empty() const *     { *         if( -1 == m_iBack || m_iFront > m_iBack)  //在连续删除不插入的时候就有可能出现 m_iFront > m_iBack的时候 *              return true; *         return false; *     } *     void pop()               //删除队首元素 *     { *         if(true == empty()) *              return; *         else *         { *              m_pArray[m_iFront].~T(); *              ++m_iFront;             //将数组的左端当做队列首部,这样能使得插入和删除的时间复杂度都是O(1) *         } *     } *     void push() *     { *         //将数组的右端视为队列的尾部 *         if( m_iBack  >= m_iMaxSize-1 )                       //说明此队列已经满了 *         { *              return;                 //其实应该是扩大数组容量, 迁移元素,但是这个类要讨论的不是这种实现方式,或者将队列整体左移 *         } *         ++m_iBack; *         m_pArray[m_iBack] = T; *      } * private: *     int m_iMaxSize{100};             //队列的最大大小 *     int m_iFront{ -1 };              //队首元素的索引 *     int m_iBack{ -1 };               //队尾元素的索引 *     T *m_pArray{nullptr}; * } * 通过上面的简单实现,可以看出一个问题,当逐步执行删除操作时,会造成较大的空间浪费    *//*方式三:循环队列,就是将一维数组首尾相连视为一个环,每个元素的位置由公式             *//*现在队列是一个环形,那么意味着每一个元素都有其下一个位置和前一个位,此时确定第i个    *//*元素的位置,使用公式:location(i) = (location(0)(队首元素的位置) + i ) % arrayLength *//*公式中arrayLength是你为这个队列分配的一维数组的大小,而location(0)则是队首元素的位置 *//*由公式可知要知道第i个元素的位置,必须要知道第0个元素的位置,假定和队首元素位置相关的 *//*变量其名字为queueFront,现在我们约定,queueFront指向的不是队首元素,而是沿逆时针方向 *//*指向队首元素的下一位置                                                               *//*另外,依然使用一个变量来记录队尾元素的位置,假设名字为queueBack,它直接指向队尾元素  *//***************************************************************************************/
#ifndef ARRAYQUEUE_H_#define ARRAYQUEUE_H_//本例中使用环形数组来描述这个队列#include <stdexcept>#include <cmath>#include <new>#include <algorithm>template <typename T>class ArrayQueue{public:    bool empty() const    {        //这个判断条件意味着,在这个数组中,我们永远留着一个空位,确保m_iTheFront和m_iTheRear除了初始情况之外,永远不会存在相等的情况        //所以在每一次的插入操作之前,都需要先判断一下本次操作会不会让队列变满,如果会,那么就扩充数组容量,然后再执行插入操作,        //按照这种策略,队列中的元素个数最多只能是 m_iArraySize - 1        if(m_iTheFront == m_iTheRear)            return true;        return false;    }    void push(const T &element);        //在队尾插入元素    void pop();                         //在队首删除元素    T& front();                         //返回队首元素    T& back();                          //返回队尾元素    int size() const;                           //返回队列中元素的个数    int maxsize() const;                        //返回队列能容纳的最大元素个数    ArrayQueue();    ~ArrayQueue();private:    int m_iTheFront{0}; //指向队列首元素的游标,重要,初始情况下,m_iTheFront和m_iTheRear的值都是0    int m_iTheRear{0};          //指向队列尾元素的游标    int m_iArraySize{10};    T *m_pArray{nullptr};    void expandCapacity();      //扩充一维数组的容量};
template <typename T>void ArrayQueue<T>::push(const T &element){   if( (m_iTheRear + 1) % m_iArraySize == m_iTheFront )   {        expandCapacity();        //如果下一个插入位置刚好和首元素逆时针方向上的下一位置游标相等,说明这个队列已经满了   }   m_iTheRear = (m_iTheRear + 1) % m_iArraySize;   m_pArray[m_iTheRear] = element;}
template <typename T>void ArrayQueue<T>::pop(){    if(true == empty())        return;    m_iTheFront = (m_iTheFront + 1) % m_iArraySize;    m_pArray[m_iTheFront].~T();}
template <typename T>T& ArrayQueue<T>::front(){    if(true == empty())        throw std::runtime_error("Empty Queue");    //先计算出队列首元素的位置,然后返回它的值    return m_pArray[(m_iTheFront + 1) % m_iArraySize];}
template <typename T>T& ArrayQueue<T>::back(){    //返回队列的尾部元素,m_iTheRear这个游标直接指向队尾元素    if(true == empty())        throw std::runtime_error("Empty Queue");    return m_pArray[m_iTheRear];}
template <typename T>int ArrayQueue<T>::size() const{    //循环队列的大小计算分为两种情况    //情形一:m_iTheFront < m_iTheRear,那么队列的大小就是 m_iTheRear - m_iTheFront    //情形二:m_iTheFront > m_iTheRear,那么计算起来就分为两部分了,一部分是 0 + m_iTheRear,另一部分是 m_iArraySize - m_iTheFront,所以合起来就是    //m_iTheRear + m_iArraySize - m_iTheFront    //把上述两种情况合在一起,那么计算大小的公式就是  (m_iTheRear - m_iTheFront + m_iArraySize) % m_iArraySize    return (m_iTheRear - m_iTheFront + m_iArraySize) % m_iArraySize;}
template <typename T>int ArrayQueue<T>::maxsize() const{    return m_iArraySize - 1;    //数组中最多只能存储最大大小减去一个位置的元素}
template <typename T>ArrayQueue<T>::ArrayQueue(){    //如果分配内存失败的话,会抛出一个bad_alloc的异常,记得使用时捕获它    m_pArray = new T[m_iArraySize * sizeof(T)];}
template <typename T>ArrayQueue<T>::~ArrayQueue(){    for(int i = 0; i < m_iArraySize; ++i)    {        //析构函数,要把数组中的每一对象释放了,因为new的时候会调用默认构造函数,如果是使用了内存分配器allocate,那么要进行更加精细的操作        m_pArray[i].~T();    }    if(nullptr != m_pArray)    {        delete[] m_pArray;        m_pArray;    }}
template <typename T>void ArrayQueue<T>::expandCapacity(){    //首先计算出队列首元素的在数组中所在的索引,现在我们把这个一维数组视为一个环形,这里的m_iTheFront指向的是自队列首元素结点处逆时针方向的下一位置    //但是它本质上其实还是一个一维数组,一维数组它在内存中的索引从0开始,那么怎么判断目前的结构是不是形成了一个环呢?    //只要m_iTheRear(尾元素游标)和 m_iTheFront(首元素处逆时针下一位置游标)都处于0以及0之后的索引,那么就认为它形成了一个环。
    //求出队列首元素实际的存储位置,因为我们是把一维数视为环形的,并且m_iTheFront是首元素逆时针方向的下一位置,将它想象成一个环,可以得到求首元素位置的公式为:    // (m_iTheFront + 1) % m_iArraySize(数组大小),要对数组大小取模,是因为,你的环,每一个位置上的索引是固定的,不是无限增长的。
    int iStart = (m_iTheFront + 1) % m_iArraySize;              //队列首元素的位置索引    T *newQueue = new (std::nothrow) T[2 * m_iArraySize];    if(iStart < 2)    {        //没有形成环        std::copy(m_pArray + iStart , m_pArray + iStart + m_iArraySize - 1,newQueue);    }    else    {        //形成环        std::copy(m_pArray+iStart,m_pArray+m_iArraySize,newQueue);        std::copy(m_pArray,m_pArray + m_iTheRear + 1,newQueue + m_iArraySize - iStart);    }    //设置新的队列的首元素和尾元素的位置    m_iTheFront = 2*m_iArraySize - 1;    m_iTheRear = m_iArraySize - 2;      // 这里是m_iArraySize -2 ; -2 的原因是满队列的情况下还要留出一个位置,然后索引最大是m_iArraySize -2.综合起来就得到了-2这个结论    m_iArraySize *= 2;    delete [] m_pArray;    m_pArray = newQueue;}
template <typename T>class Node{public:    Node() = default;    Node(const T& element) : m_Element(element){};    Node(const T& element,const Node<T> *pNext):m_Element(element),m_pNextNode(pNext) {};    T m_Element;    Node<T> *m_pNextNode{nullptr};};
template <typename T>class LinkedQueue{public:    bool empty() const    {        if(nullptr == m_pFront)            return true;        return false;    }    int size() const    {        return m_iSize;    }    T& front() const;           //返回队列的队首元素    T& back() const;            //返回队列的队尾元素    void push(const T& element);        //从队列的尾部插入元素    void pop();                         //删除队列首部的元素    LinkedQueue() = default;    ~LinkedQueue();private:    Node<T> *m_pFront{nullptr};                 //队列的首部    int m_iSize{0};                             //队列大小    Node<T> *m_pBack{nullptr};                  //队列的尾部    void clear();                               //清理数据结构};
template <typename T>T& LinkedQueue<T>::front() const{    if(false == empty())        return m_pFront->m_Element;}
template <typename T>T& LinkedQueue<T>::back() const{    if(false == empty())        return m_pBack->m_Element;}
template <typename T>void LinkedQueue<T>::push(const T &element){    Node<T> *pNewNode = new(std::nothrow) Node<T>(element);    if(nullptr == pNewNode)        return;    if(m_iSize == 0)    {        //如果大小等于0,那么说明,这是第一个被插入链表的元素        m_pFront = pNewNode;            //这时候时头指针指向新的结点    }    else    {        //队列不为空,此时链表的生成方向有两种,一种是从头部开始链接,另一种从尾部开始链接,当你写到pop函数的时候就能发现如果从尾部开始链接,删除会变的很复杂,因为我们的链表是单向的        m_pBack->m_pNextNode = pNewNode;    //令新结点的指针域指向记录尾结点位置的m_pBack    }    m_pBack = pNewNode;                 //更新尾结点    ++m_iSize;}
template <typename T>void LinkedQueue<T>::pop(){    if(true == empty())        return;    Node<T> *pTemp = m_pFront;          //保存一下队首元素的位置,这个待会要删除结点用    m_pFront = pTemp->m_pNextNode;    pTemp->m_Element.~T();              //销毁对象    if(pTemp != nullptr)    {        delete pTemp;        pTemp = nullptr;    }    --m_iSize;    if( 0 == m_iSize)        m_pFront = m_pBack = nullptr;}
template <typename T>void LinkedQueue<T>::clear(){    for(int i=0; i < m_iSize; ++i)    {        Node<T> *pTempNode = m_pFront;        m_pFront = pTempNode->m_pNextNode;        if(nullptr != pTempNode)        {             delete pTempNode;             pTempNode = nullptr;        }    }    m_pFront = m_pBack = nullptr;}
template <typename T>LinkedQueue<T>::~LinkedQueue(){    clear();}#endif

转载于:https://www.cnblogs.com/ToBeExpert/p/10303605.html

队列——数组实现和链式实现相关推荐

  1. java链式结构_java语言实现队列顺序结构与链式结构

    本文主要向大家介绍了java语言实现队列顺序结构与链式结构,通过具体的内容向大家展示,希望对大家学习java语言有所帮助. 队列的顺序存储结构实现 public class Queue{ privat ...

  2. 【数据结构笔记06】队列及其顺序存储、链式存储

    本次笔记内容: 2.3.1 队列及顺序存储实现 2.3.2 队列的链式存储实现 文章目录 什么是队列 队列的顺序存储实现 循环队列 队列的链式存储实现 什么是队列 队列(Queue):具有一定操作约束 ...

  3. 队列的顺序、链式表示与实现

           上期说到栈,是一种"先进后出"的线性表,今天我们来剖析一下一种 " 先进先出 " 的数据结构:队列. 队列也有顺序表示和链式表示. 一.队列的顺序 ...

  4. 链队列的基本运算java_链式队列基本操作的实现问题

    问题描述:用链式存储方式实现队列的基本操作 涉及变量:front:Node型自定义变量,指向队首元素 rear:Node型自定义变量,指向队尾元素 涉及教材:<数据结构--Java语言描述(第2 ...

  5. 二叉树的存储方式【顺序储存(数组)、链式存储、邻接表存储等】

    其他二叉树知识!二叉树知识汇总 目录 前言: 1.顺序存储结构 2.链式存储结构 3.二维数组直接存储 4.邻接表存储 前言: 顺序存储和链式存储是经典讲解的内容,本文做简单理论介绍,而对于后两种:二 ...

  6. 数据结构—栈与队列【顺序存储、链式存储、卡特兰数、优先级队列】

  7. c语言队列如何表示,队列的链式表示和实现(C语言)

    #include #include #define OK 1; #define ERROR 0; #define OVERFLOW 0; #define TURE 1; #define FALSE 0 ...

  8. 【数据结构】链式队列的实现(C语言)

    队列的链式存储称为链式队列.链式队列就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除操作规定在单链表的不同端进行.链式队列的队首和队尾指针分别用front和rear表示. 链式队列要掌握以下 ...

  9. 队列的链式存储和实现(C语言)【队列】(8)

    LinkQueue.h DataType.h DataType.cpp LinkQueue.cpp 测试结果 LinkQueue.h #pragma once#include "DataTy ...

  10. (C语言版)栈和队列(一)——实现链式栈和链式队列的基本操作以及遇到的问题

    http://blog.csdn.net/fisherwan/article/details/20055179 首先要感谢这位大牛的一篇博客,地址如下:http://blog.csdn.net/hgu ...

最新文章

  1. [Dynamic Language] Python 静态方法、类方法、属性
  2. 如果你想成为年入 50w+ 的架构师,我建议你先看看这个...
  3. 小程序直播间页面路径怎么访问直播间_以小程序为例,在线教育产品的直播间有哪些功能设计?...
  4. delphi socket 流的使用_Socket
  5. C - 思考使用差分简化区间操作
  6. python3 读取文本文件_python3读取文件最简单的办法
  7. 数据结构 --- 线性表学习(php模拟)
  8. setValuesForKeysWithDictionary:的用途
  9. 1.Entity Framework Core 5.0教程,概述和准备
  10. android抓取微信朋友圈,一种快速提取Android微信朋友圈数据的方法
  11. 基于DMD实现透过多模光纤(MMF)的聚焦
  12. python制作日历并保存成excel_Python+Excel制作精美壁纸日历,任意DIY
  13. (附源码)计算机毕业设计SSM-志愿者管理系统
  14. 我不 大冰2017新书pdf免费下载
  15. Android 7.0修改PMS逻辑添加权限白名单
  16. 第五人格亚服服务器不稳定,【关于第五人格网络问题的部分原因及解决方法】...
  17. MinIO客户端(mc命令)实现数据迁移
  18. java pdf库_Java中常用的操作PDF的类库
  19. java 开发程序IDE
  20. 怎样用AIDL Service 传递复杂数据

热门文章

  1. Vue:列表渲染 v-for on a template
  2. 在 Linux 上如何清除内存的 Cache、Buffer 和交换空间
  3. 浅析阿里数据技术架构(下)大规模分布式知识图谱
  4. radio change事件
  5. ASP.NET MVC+EF框架+EasyUI实现权限管理系列
  6. Nagios插件开发指导
  7. 每天学一点flash(4) 数组与xml配合使用
  8. 【JAVA单元测试】单元测试模拟高并发操作
  9. iOS could not set nil as the value for the key
  10. 又整理了一批可以拿去做副业的开源项目...