数据结构之队列

头文件queue.h:

#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED

const int maxSize = 50;
enum bool{false,true};
template<typename T>
class Queue
{
public:
    Queue(){};
    ~Queue(){};
    virtual void EnQueue(const T& x) = 0;
    virtual void DeQueue(T& x) = 0;
    virtual bool getFront(T& x) = 0;
    virtual bool IsEmpty()const = 0;
    virtual bool IsFull()const = 0;
    virtual int getSize()const = 0;
};

template <typename T>
struct LinkNode
{
    T data;
    LinkNode<T> *link;
    LinkNode(LinkNode<T>* ptr = NULL){link = ptr;}
    void LinkNOde(const T& item, LinkNode<T> *ptr = NULL)
    {
        data = item;
        link = ptr;
    }
};

#endif // QUEUE_H_INCLUDED

实现函数queue_list.cpp:

#include <iostream>
#include "queue.h"
using namespace std;
template <typename T>
class LinkedQueue:public Queu<T>
{
public:
    LinkedQueue():rear(NULL),myfront(NULL){}
    ~LinkedQueue(makeEmpty());
    bool EnQueue(const T& x);
    bool DeQueue(T& x);
    bool getFront(T& x)const;
    void makeEmpty();
    bool IsEmpty()const{return (myfront == NULL) ? true : false;}
    int getSize()const;
    friend ostream& operator<<(ostream& os, LinkedQueue<T>& Q);
protected:
    LinkNode *myfront, *rear;
};

template <typename T>
void LinkedQueue<T>::makeEmpty()
{
    LinkNode<T> *p;
    while(myfront != NULL)
    {
        p = myfront;
        myfront = myfront->link;
        delete p;
    }
}

template <typename T>
bool LinkedQueue<T>::EnQueue(const T& x)
{
    if(myfront == NULL)//判断是不是空队列
    {
        myfront =rear = new LinkNode<T>(x);
        if(myfront == NULL)
            return false;
    }
    else
    {
        rear->link = new LinkNode<T>(x);
        if(rear->link == NULL) return false;
        rear = rear->link;
    }
    return true;
}

template <typename T>
bool LinkedQueue<T>::DeQueue(T& x)
{
    if(IsEmpty () == true) return false;
    LinkNode<T> *p = myfront;
    x = myfront->data;
    myfront = myfront->link;
    delete p;
    return true;
}

template <typename T>
bool LinkedQueue<T>::getFront(T& x)
{
    if(IsEmpty() == true) return false;
    x = myfront->data;
    return true;
}

template <typename T>
int LinkedQueue<T>::getSize()const
{
    LinkNode<T> *p = myfront;
    int k = 0;
    while(p != NULL)
    {
        p = p->link;
        k++;
    }

}

template <typename T>
ostream& operator<<(ostream& os,LinkedQueue<T>& Q)
{
    os<<"队列中的元素个数有"<<Q.getSize()<<endl;
    LinkNode<T> *p;
    int i = 0;
    while(p != NULL)
    {
        os<<++i<<":"<<p->data<<endl;
        p = p->link;
    }
    return os;
}

代码均通过CB编译。用单链表表示的链式队列特别适合于数据元素变动比较大的情形,而且不存在队列满溢出的情况。上述为一般的队列(用链表实现)


我记得刚开始学数据结构的时候,听的是浙江大学的数据结构,跟完一遍课之后发现根本就没有懂。比如说在删除的时候为什么要先判空啊;在遍历队列中的元素时为什么要重新申请一个节点指针,使它指向队头的节点。


为了解决假溢出的问题,我们提出了一种循环队列。还是用数组的方式来存储数据。

头文件:

#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED

//int maxSize = 50;
//enum bool{false,true};
template<typename T>
class Queue
{
public:
    Queue(){};
    ~Queue(){};
    virtual bool EnQueue(const T& x) = 0;
    virtual bool DeQueue(T& x) = 0;
    virtual bool getFront(T& x) = 0;
    virtual bool IsEmpty()const = 0;
    virtual bool IsFull()const = 0;
    virtual int getSize()const = 0;
};

template <typename T>
struct LinkNode
{
    T data;
    LinkNode<T> *link;
    LinkNode(LinkNode<T>* ptr = NULL){link = ptr;}
    void LinkNOde(const T& item, LinkNode<T> *ptr = NULL)
    {
        data = item;
        link = ptr;
    }
};

#endif // QUEUE_H_INCLUDED

循环链表的实现:

#include <assert.h>
#include <iostream>
#include "Queue.h"
using namespace std;
template <typename T>
class SeqQueue:public Queue<T>
{
public:
    SeqQueue(int sz = 10);
    ~SeqQueue()
    {
        delete[]elements;
    }
    bool EnQueue(const T& x);
    bool DeQueue(T& x);
    bool getFront(T& x);
    void makeEmpty()
    {
        myfront = rear = 0;
    }
    bool IsEmpty()const
    {
        return (myfront == rear) ? true : false;
    }
    bool IsFull()const
    {
        return ((rear + 1) % maxSize == myfront) ?  true : false;
    }
    int getSize()const
    {
        return(rear - myfront + maxSize) % maxSize;
    }
    int getMaxSize()const
    {
        return maxSize;
    }
    template <typename U>
    friend ostream& operator << (ostream& os, SeqQueue<U>& Q);
protected:
    int rear,myfront;
    T *elements;
    int maxSize;
};

template <typename T>
SeqQueue<T>::SeqQueue(int sz):myfront(0),rear(0),maxSize(sz)
{
    elements = new T[maxSize];
    assert(elements != NULL);
}

template <typename T>
bool SeqQueue<T>::EnQueue(const T& x)
{
    if(IsFull() == true) return false;
    elements[rear] = x;
    rear = (rear + 1) % maxSize;
    return true;
}

template <typename T>
bool SeqQueue<T>::DeQueue(T& x)
{
    if(IsEmpty() == true) return false;
    x = elements[myfront];
    myfront = (myfront + 1) % maxSize;
    return true;
}

template <typename T>
bool SeqQueue<T>::getFront(T& x)
{
    if(IsEmpty() == true) return false;
    x = elements[myfront];
    return true;
}

template <typename U>
ostream& operator << (ostream& os, SeqQueue<U>& Q)
{
    os << "myfront = " << Q.myfront << ",rear = " << Q.rear << endl;
    for(int i = Q.myfront; i != Q.rear;i = (i + 1) % Q.maxSize )
        os << i <<":" << Q.elements[i] << endl;
    return os;
}
int main()
{   int x;
    SeqQueue<int> myqueue(8);
    cout << myqueue.getMaxSize() << endl;
    myqueue.EnQueue(100);
    myqueue.EnQueue(1);
    myqueue.EnQueue(1);
    myqueue.EnQueue(1);
    myqueue.EnQueue(1);
    myqueue.EnQueue(1);
    myqueue.EnQueue(1);
    //myqueue.EnQueue(1);
    myqueue.DeQueue(x);
    cout<< x << endl;
    myqueue.EnQueue(200);
    myqueue.EnQueue(200);
    cout<< "myqueue: " << myqueue <<endl;
}
运行结果

我在编的时候参考的是殷人昆主编的第二版的《C++数据结构》,书里面还是有不少的问题。难道是编译环境有所差别?

PS:在调试的时候有些地方值得注意:

首先,在用友元函数重载类SeqQueue的operator <<  时候,编译器报错。原因是该友元函数在类中的声明使用template<typename T> 构成了对类的依赖,而友元函数相对于类是独立的,它不应该对类构成依赖。google之后参考了他人的博客解决了问题。解决问题的办法主要有两种。第一种:将友元函数的实现放在类的内部。第二种:在类的内部声明友元函数的时候为它单独配一个模板类型,然后在外部实现。我代码里面用的是第二种方法,经过调试第一种方法也是可行的。

第二,书中好多地方代码都是有误的,比如此程序中的重载输出运算符的函数中,在访问SeqQueue类型Q对象的私有成员的时候应该是以Q.maxSize,Q.myfront,Q.rear的形式来访问的,否则咋访问数据时候可能出现歧义。

第三,程序仍有一些存在风险的警告,仍需后续的解决。


队列还有补充的内容,还有为什么富文本编辑器的水平线删除不掉。。。

借助vector实现队列(存在假溢出的情况)PS:简单但是很低效。。。

#include <iostream>
#include <vector>
using namespace std;
class MyQueue{
    vector<int> data;
    int p_start;
public:
    MyQueue(){p_start = 0;}

    bool enQueue(int x){
        data.push_back(x);
        return true;
    }
    bool deQueue(){
        if(isEmpty()) return false;
        ++p_start;
        return true;
    }
    int Front(){
        return data[p_start];
    }
    bool isEmpty()
    {
        return p_start >= data.size();
    }
};
int main() {
    MyQueue q;
    q.enQueue(5);
    q.enQueue(3);
    if (!q.isEmpty()) {
        cout << q.Front() << endl;
    }
    q.deQueue();
    if (!q.isEmpty()) {
        cout << q.Front() << endl;
    }
    q.deQueue();
    if (!q.isEmpty()) {
        cout << " q.Front()"<< endl;
    }
}

借助vector的循环队列的实现

class MyCircularQueue {
private:
    vector<int> data;
    int head;
    int tail;
    int size;
public:
    /** Initialize your data structure here. Set the size of the queue to be k. */
    MyCircularQueue(int k) {
        data.resize(k);
        head = -1;
        tail = -1;
        size = k;
    }
    
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    bool enQueue(int value) {
        if (isFull()) {
            return false;
        }
        if (isEmpty()) {
            head = 0;
        }
        tail = (tail + 1) % size;
        data[tail] = value;
        return true;
    }
    
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    bool deQueue() {
        if (isEmpty()) {
            return false;
        }
        if (head == tail) {
            head = -1;
            tail = -1;
            return true;
        }
        head = (head + 1) % size;
        return true;
    }
    
    /** Get the front item from the queue. */
    int Front() {
        if (isEmpty()) {
            return -1;
        }
        return data[head];
    }
    
    /** Get the last item from the queue. */
    int Rear() {
        if (isEmpty()) {
            return -1;
        }
        return data[tail];
    }
    
    /** Checks whether the circular queue is empty or not. */
    bool isEmpty() {
        return head == -1;
    }
    
    /** Checks whether the circular queue is full or not. */
    bool isFull() {
        return ((tail + 1) % size) == head;
    }
};

队列的用法:

#include <iostream>

int main() {
    // 1. Initialize a queue.
    queue<int> q;
    // 2. Push new element.
    q.push(5);
    q.push(13);
    q.push(8);
    q.push(6);
    // 3. Check if queue is empty.
    if (q.empty()) {
        cout << "Queue is empty!" << endl;
        return 0;
    }
    // 4. Pop an element.
    q.pop();
    // 5. Get the first element.
    cout << "The first element is: " << q.front() << endl;
    // 6. Get the last element.
    cout << "The last element is: " << q.back() << endl;
    // 7. Get the size of the queue.
    cout << "The size is: " << q.size() << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值