数据结构面试之四——队列的常见操作

107 阅读3分钟

数据结构面试之四——队列的常见操作

题注:《面试宝典》有相关习题,但思路相对不清晰,排版有错误,作者对此参考相关书籍和自己观点进行了重写,供大家参考。

四、队列的基本操作

1.用数组构造队列

队列即是满足先进先出的链表。用数组存储的话,同样需要满足队列头front出栈,队列末尾rear入栈。而对于数组来讲,rear和front可以代表数组头和尾。不能简单的固定rear和front的大小为maxSize和0,因为可能出现中间元素为空的现象。所以,对于数组队列来讲,可以想象成环式存储,因为每一次入队后rear+1,每一次出队后front+1。这就需要控制front和rear的大小,每一次修改只要满足front=(front+1)%maxSize,rear=(rear+1)%maxSize即可满足要求。

       同样需要注意:入队操作前先判定队列是否已经满;出队操作前先判定队列是否为空。

template<typename Type>
class arrQueue
{
public:
       arrQueue(intnSize=100);
       ~arrQueue();
       arrQueue(constarrQueue<Type>& copyQueue);
       arrQueue&operator=(const arrQueue<Type>& otherQueue);
 
       voidinitializeQueue();
       void destroyQueue();
       bool isQueueEmpty();
       bool isQueueFull();
       void addQueue(constType& item);
       void deQueue(Type&deletedItem);
 
private:
       int maxSize;
       int rear;
       int front;
       Type* list;
};
 
template<typename Type>
arrQueue<Type>::arrQueue(int nSize=100)
{
       if(nSize < 0)
       {
              nSize = 100;
              list = newType[nSize];
              front = 0;
              rear = 0;
              maxSize = 100;
       }
       else
       {
              list = newType[nSize];
              front = 0;
              rear = 0;
              maxSize =nSize;
       }
}
 
template<typename Type>
arrQueue<Type>::~arrQueue()
{
       if(!list)
       {
              delete[]list;                  //注意数组的删除,为delete []list;
              list = NULL;
       }
}
 
template<typename Type>
arrQueue<Type>::arrQueue(const arrQueue<Type>©Queue)
{
       maxSize =copyQueue.maxSize;
       front =copyQueue.front;
       rear = copyQueue.rear;
       list = newType[maxSize];            //注意需要自定义大小,容易出错.
       for( int i = 0; i <rear; i++)
       {
              list[i] =copyQueue.list[i];
       }
}
 
template<typename Type>
arrQueue<Type>& arrQueue<Type>::operator=(constarrQueue<Type>& otherQueue)
{
       if(this ==&otherQueue)
       {
              cout <<"can't copy oneSelf!" << endl;
              return *this;
       }
       else
       {
              if(maxSize !=otherQueue.maxSize)
              {
                     cout<< "The Size of two Queue are not equal!" << endl;
                     return*this;
              }
              else
              {
                     maxSize= otherQueue.maxSize;
                     front =otherQueue.front;
                     rear =otherQueue.rear;
                     for( inti = 0; i < rear; i++)
                     {
                            list[i]= otherQueue.list[i];
                     }//endfor
                     return*this;
              }
       }//end else
}
 
template<typename Type>
void arrQueue<Type>::initializeQueue()
{
       destroyQueue();
}
 
template<typename Type>
void arrQueue<Type>::destroyQueue()
{
       front = 0;
       rear = 0;
}
 
//栈空的判定标志rear==front[初始]
template<typename Type>
bool arrQueue<Type>::isQueueEmpty()
{
       return (rear ==front);
}
 
//空余1位作为判定位,可以把存储结构想象成环!
//注意栈满的判定:1.保证空间都被占用;
//2.保证rear的下一个位置=front即为满。
template<typename Type>
bool arrQueue<Type>::isQueueFull()
{
       return((rear+1)%maxSize == front); 
}
 
template<typename Type>
void arrQueue<Type>::addQueue(const Type& item)
{
       if(!isQueueFull())
       {
              list[rear] =item;
              rear =(rear+1)%maxSize;
              cout << item<< " was added to Queue!" << endl;
       }
       else
       {
              cout <<"The Queue was already Full!" << endl;
       }
}
 
template<typename Type>
void arrQueue<Type>::deQueue(Type& deletedItem)
{
       if(!isQueueEmpty())
       {
              deletedItem =list[front];
              front =(front+1)%maxSize;                  //注意此处的判定!
              cout <<deletedItem << " was deleted from Queue!" << endl;
       }
       else
       {
              cout <<"The Queue was already Empty!" << endl;
       }
}

2.队列采用链表链式存储结构

注意:1)此时的front和rear都变成了指针,front变成了头结点指针,而rear变成了尾节点的指针。2)此处的front和rear类似于链表操作中的first和last。3)入队实现主要在队列尾部实现,需要调整rear指针的指向;而出队操作主要在队头实现,需要调整front指针的指向。

template<typename Type>
struct nodeType
{
       Type info;
       nodeType* link;
};
 
template<typename Type>
class linkedQueue
{
public:
       linkedQueue();
       ~linkedQueue();
       linkedQueue(constlinkedQueue<Type>&);
       linkedQueue&operator=(const linkedQueue<Type>&);
 
       voidinitializeQueue();
       void destroyQueue();
       bool isQueueEmpty()const;
       bool isQueueFull()const;
       void addQueue(constType& item);
       void deQueue(Type&poppedItem);
       void nodeCount();
 
private:
       nodeType<Type>*rear;
       nodeType<Type>*front;
       int count;         //统计节点个数
};
 
template<typename Type>
linkedQueue<Type>::linkedQueue()
{
       count = 0;
       front = NULL;
       rear = NULL;
}
 
template<typename Type>
linkedQueue<Type>::~linkedQueue()
{
       while( front != NULL )
       {
              nodeType<Type>*tempNode = new nodeType<Type>;
              tempNode =front;
              front =front->link;
 
              deletetempNode;
       }
       //注意rear的清空
       rear = NULL;
}
 
template<typename Type>
linkedQueue<Type>::linkedQueue(constlinkedQueue<Type>& copyQueue)
{
       if(copyQueue.front !=NULL)
       {
              nodeType<Type>*current;
              nodeType<Type>*first;
              nodeType<Type>*newNode;
 
              front = newnodeType<Type>;
              front->info= copyQueue.front->info;          //此处的top不能直接用,内存报错!
              front->link= copyQueue.front->link;
 
              first =front;                        //first跟进当前链表...
              current =copyQueue.front->link;      //current跟进copy链表...
              while( current!= NULL)
              {
                     newNode= new nodeType<Type>;
                     newNode->link= current->link;
                     newNode->info= current->info;
 
                     first->link= newNode;
                     first =newNode;
                     current= current->link;
              }//end while
              rear = current;
              count =copyQueue.count;
       }//end if
       else
       {
              front = NULL;
              rear = NULL;
              count = 0;
       }
}
 
template<typename Type>
linkedQueue<Type>& linkedQueue<Type>::operator=(constlinkedQueue<Type>& otherQueue)
{
       //1避免自身赋值
       if(this ==&otherQueue)
       {
              cout <<"Can't copy oneself!" << endl;
              return *this;
       }
       //2其他
       else
       {
              if(front !=NULL)
              {
                     destroyQueue();
              }
              if(otherQueue.front!= NULL)
              {
                     nodeType<Type>*current;
                     nodeType<Type>*first;
                     nodeType<Type>*newNode;
 
                     front =new nodeType<Type>;
                     front->info= otherQueue.front->info;
                     front->link= otherQueue.front->link;
                     first =front;                        //first跟进当前链表...
                     current= otherQueue.front->link;     //current跟进copy链表...
                     while(current != NULL)
                     {
                            newNode= new nodeType<Type>;
                            newNode->link= current->link;
                            newNode->info= current->info;
 
                            first->link= newNode;
                            first= newNode;
                            current= current->link;
                     }//endwhile
                     rear =current;
                     count =otherQueue.count;
              }//end if
              else
              {
                     front =NULL;
                     rear =NULL;
                     count =0;
              }
              return *this;
       }
}
 
template<typename Type>
void linkedQueue<Type>::initializeQueue()
{
       destroyQueue();
}
 
template<typename Type>
void linkedQueue<Type>::destroyQueue()
{
       count = 0;
       //注意此处的销毁工作:需要循环判定!
       while(front != NULL)
       {
              nodeType<Type>*temp = new nodeType<Type>;
              temp = front;
              front =front->link;
       }
 
       rear = NULL;
}
 
template<typename Type>
bool linkedQueue<Type>::isQueueEmpty() const
{
       return (front ==NULL);
}
 
template<typename Type>
bool linkedQueue<Type>::isQueueFull() const //空间非固定,动态申请!
{
       return false;
}
 
template<typename Type>
void linkedQueue<Type>::addQueue(const Type& item)
{
       if(!isQueueFull())
       {
              nodeType<Type>*newNode = new nodeType<Type>;
              newNode->info= item;
              newNode->link= NULL;
 
              if(front ==NULL)
              {
                     front =newNode;
                     rear =newNode;
              }
              else
              {
                     rear->link= newNode;
                     rear =newNode;
              }
              count++;
              cout <<item << " was pushed!" << endl;
       }
}
 
template<typename Type>
void linkedQueue<Type>::deQueue(Type& deletedItem)
{
       if(!isQueueEmpty())
       {
              nodeType<Type>*temp = new nodeType<Type>;
              temp = front;
              deletedItem =front->info;
              front =front->link;
 
              count--;
              cout <<deletedItem << " was popped!" << endl;
              delete temp;
       }
}
 
template<typename Type>
void linkedQueue<Type>::nodeCount()
{
       cout <<"nodeCount = " << count << endl;
}
 

\

3.用栈实现队列

注意栈是先进后出,而用两个栈:栈1先进后出,栈2在栈1的基础上先进后出,就能实现了先进先出。

注意:入队addtoQueue要保证将元素放入到栈1中;而对于出队deQueue要保证将栈1的全部元素出栈pop,然后再全部入栈2,最后执行出栈2操作即可。

#include"linkedStack.h"
template<typename Type>
class stackedQueue
{
public:
       stackedQueue();
       ~stackedQueue();
 
       void addQueue(Type item);
       void deQueue(Type deletedItem);
      
       bool isQueueEmpty();
       bool isQueueFull();
 
private:
       nodeType<Type>* front;
       nodeType<Type>* rear;
       linkedStack<Type>* firstStack;
       linkedStack<Type>* secondStack;
       int nodeCnt;    //记录节点个数
};
 
template<typename Type>
stackedQueue<Type>::stackedQueue()
{
       front = NULL;
       rear = NULL;
    nodeCnt = 0;
      
       firstStack = new linkedStack<Type>;
       secondStack = new linkedStack<Type>;
}
 
template<typename Type>
stackedQueue<Type>::~stackedQueue()
{
       while(front != NULL)
       {
              nodeType<Type>* temp;
              temp = front;
              front = front->link;
       }
       rear = NULL;
       if(firstStack != NULL)
       {
              delete firstStack;
              firstStack = NULL;
       }
       if(secondStack != NULL)
       {
              delete secondStack;
              secondStack = NULL;
       }
}
 
template<typename Type>
voidstackedQueue<Type>::addQueue(Type item)
{
       if(!isQueueFull())
       {
              nodeCnt++;
              firstStack->push(item);        //单个入栈1
              cout << item << " was added toQueue!" << endl;
       }
}
 
template<typename Type>
voidstackedQueue<Type>::deQueue(Type deletedItem)
{
       if(!isQueueEmpty())
       {
              while(!firstStack->isStackEmpty())
              {
                     firstStack->pop(deletedItem);              //全部出栈1
                     if(!firstStack->isStackFull())
                     {
                            secondStack->push(deletedItem);       //全部入栈2
                     }
              }
              if(!secondStack->isStackEmpty())
              {
                     secondStack->pop(deletedItem);            //单个出栈2
              }
              cout << deletedItem << " was out ofQueue!" << endl;
              nodeCnt--;
       }
}
 
template<typename Type>
boolstackedQueue<Type>::isQueueEmpty()
{
       return (nodeCnt == 0);
}
 
template<typename Type>
boolstackedQueue<Type>::isQueueFull()
{
       return false;
}


第四节结束。

\