数据结构面试之四——队列的常见操作
来源:互联网 发布:中文域名的作用 编辑:程序博客网 时间:2024/06/08 14:50
数据结构面试之四——队列的常见操作
题注:《面试宝典》有相关习题,但思路相对不清晰,排版有错误,作者对此参考相关书籍和自己观点进行了重写,供大家参考。
四、队列的基本操作
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;}
第四节结束。
- 数据结构面试之四——队列的常见操作
- 数据结构面试之四——队列的常见操作
- 数据结构面试之四——队列的常见操作
- 数据结构面试之三——栈的常见操作
- 数据结构面试之七——图的常见操作
- 数据结构面试之三——栈的常见操作
- 数据结构面试之三——栈的常见操作
- 数据结构面试之八——图的常见操作2之最短路径
- 数据结构面试之九——图的常见操作3之最小生成树
- 数据结构面试之六——二叉树的常见操作2(非递归遍历&二叉排序树)
- 数据结构面试之六——二叉树的常见操作2(非递归遍历&二叉排序树)
- 数据结构面试之六——二叉树的常见操作2(非递归遍历&二叉排序树)
- 数据结构面试之五—二叉树的常见操作(递归实现部分)
- 数据结构面试之五—二叉树的常见操作(递归实现部分
- 数据结构面试之五—二叉树的常见操作(递归实现部分)
- 数据结构面试之二——双向链表表、循环链表、有序链表的常见操作
- 数据结构面试之二——双向链表表、循环链表、有序链表的常见操作
- 数据结构面试之二——双向链表表、循环链表、有序链表的常见操作
- Subversion+Apache 配置和管理
- FCKeditor 编辑器 2.6.3
- Heavy Cargo 最短路变种
- Oracle重做日志文件的基本概念
- 网络日历开发库
- 数据结构面试之四——队列的常见操作
- John's trip 欧拉回路输出路径
- Tomcat 7.0 关于mysql连接池的配置
- 进程和线程的区别
- 网页加载ocx控件,搜集的资料,有空再整理
- hdu 迷宫城堡 极大强连通分量的tarjan算法模板题
- 图论常见模型——强连通分量
- HDU 1010 Tempter of the Bone 经典深搜~DFS
- sicily--1775. Simple Sort