c++stack_和_queue用法
- 格式:pdf
- 大小:98.67 KB
- 文档页数:5
queue c++用法在C++中,队列(Queue)是一种先进先出(First-In-First-Out,FIFO)的数据结构。
队列的主要操作包括入队(enqueue)和出队(dequeue)。
在C++中,队列可以通过包含头文件`<queue>`来使用。
下面是一些队列的常用用法:1.创建队列对象:可以使用`std::queue`类来创建队列对象,语法如下:```cppstd::queue<T> queue; //创建一个空队列,其中T是要存储的元素类型```2.入队操作:可以使用`push()`方法将元素添加到队列的末尾,语法如下:```cppqueue.push(value); //将value添加到队列的末尾```3.出队操作:可以使用`pop()`方法从队列的头部删除元素,语法如下:```cppqueue.pop(); //删除队列头部的元素```4.访问队列头部元素:可以使用`front()`方法来访问队列头部的元素,语法如下:```cppT element = queue.front(); //获取队列头部的元素,存储到变量element中```5.判断队列是否为空:可以使用`empty()`方法来判断队列是否为空,语法如下:```cppbool isEmpty = queue.empty(); //如果队列为空,返回true,否则返回false```6.获取队列的大小:可以使用`size()`方法来获取队列中元素的个数,语法如下:```cppint size = queue.size(); //返回队列中元素的个数```以下是一个示例程序,演示了队列的基本使用方法:```cpp#include <iostream>#include <queue>int main() {std::queue<int> queue;//入队操作queue.push(10);queue.push(20);queue.push(30);//访问队列头部元素std::cout << "Front: " << queue.front() << std::endl; //访问队列尾部元素std::cout << "Back: " << queue.back() << std::endl; //出队操作queue.pop();//打印队列中的所有元素while (!queue.empty()) {std::cout << queue.front() << " ";queue.pop();}std::cout << std::endl;return 0;}```输出结果:```Front: 10Back: 3020 30```此外,C++的队列还支持其他一些操作,例如交换队列(`swap`)、清空队列(`clear`)等,可以根据具体需求进行拓展。
python实现stack(栈)和队列(queue)栈和队列是两种基本的数据结构,同为容器类型。
两者根本的区别在于:stack:后进先出这⾥写图⽚描述queue:先进先出这⾥写图⽚描述stack和queue是没有查询具体某⼀个位置的元素的操作的。
但是他们的排列是按顺序的对于stack我们可以使⽤python内置的list实现,因为list是属于线性数组,在末尾插⼊和删除⼀个元素所使⽤的时间都是O(1),这⾮常符合stack的要求。
当然,我们也可以使⽤链表来实现。
stack的实现代码(使⽤python内置的list),实现起来是⾮常的简单,就是list的⼀些常⽤操作class Stack(object):def __init__(object):self.stack = []def push(self, value):self.stack.append(value)def pop(self):if self.stack:self.stack.pop()else:raise LookupError('stack is empty!')def is_empty(self):return bool(self.stack)def top(self):#取出⽬前stack中最新的元素return self.stack[-1]定义如下的链表来实现队列数据结构:这⾥写图⽚描述定义⼀个头结点,左边指向队列的开头,右边指向队列的末尾,这样就可以保证我们插⼊⼀个元素和取出⼀个元素都是O(1)的操作,使⽤这种链表实现stack也是⾮常的⽅便。
实现代码如下:class Head(object):def __init__(self):self.left = Noneself.right = Noneclass Node(object):def __init__(self, value):self.value = valueself.next = Noneclass Queue(object):def __init__(self):#初始化节点self.head = Head()def enqueue(self, value):#插⼊⼀个元素newnode = Node(value)p = self.headif p.right:#如果head节点的右边不为NOne#说明队列中已经有元素了#就执⾏下列的操作temp = p.rightp.right = newnodetemp.next = newnodeelse:#这说明队列为空,插⼊第⼀个元素p.right = newnodep.left = newnodedef dequeue(self):#取出⼀个元素p = self.headif p.left and (p.left == p.right):#说明队列中已经有元素#但是这是最后⼀个元素temp = p.leftp.left = p.right = Nonereturn temp.valueelif p.left and (p.left != p.right):#说明队列中有元素,⽽且不⽌⼀个 temp = p.leftp.left = temp.nextreturn temp.valueelse:#说明队列为空#抛出查询错误raise LookupError('queue is empty!') def is_empty(self):if self.head.left:return Falseelse:return Truedef top(self):#查询⽬前队列中最早⼊队的元素if self.head.left:return self.head.left.valueelse:raise LookupError('queue is empty!')。
VC调试技巧之Call StackVC调试技巧之Call Stack简单介绍调试是程序开发者必备技巧。
如果不会调试,自己写的程序一旦出问题,往往无从下手。
本人总结10年使用VC经验,对调试技巧做一个粗浅的介绍。
希望对大家有所帮助。
今天简单的介绍介绍调用堆栈。
调用堆栈在我的专栏的文章VC 调试入门提了一下,但是没有详细介绍。
首先介绍一下什么叫调用堆栈:假设我们有几个函数,分别是function1,function2,function3,funtion4,且function1调用function2,function2调用function3,function3调用function4。
在function4运行过程中,我们可以从线程当前堆栈中了解到调用他的那几个函数分别是谁。
把函数的顺序关系看,function4、function3、function2、function1呈现出一种“堆栈”的特征,最后被调用的函数出现在最上方。
因此称呼这种关系为调用堆栈(call stack)。
当故障发生时,如果程序被中断,我们基本上只可以看到最后出错的函数。
利用call stack,我们可以知道当出错函数被谁调用的时候出错。
这样一层层的看上去,有时可以猜测出错误的原因。
常见的这种中断时ASSERT宏导致的中断。
在程序被中断时,debug工具条的右侧倒数第二个按钮一般是call stack按钮,这个按钮被按下后,你就可以看到当前的调用堆栈。
实例一:介绍我们首先演示一下调用堆栈。
首先我们创建一个名为Debug的对话框工程。
工程创建好以后,双击OK按钮创建消息映射函数,并添加如下代码:?void CDebugDlg::OnOK()?-- TODO: Add extra validation here?ASSERT(FALSE);?我们按F5开始调试程序。
程序运行后,点击OK按钮,程序就会被中断。
这时查看call stack窗口,就会发现内容如下:?CDebugDlg::OnOK() line 176 + 34 bytes_AfxDispatchCmdMsg(CCmdTarget * 0x0012fe74 {CDebugDlg}, unsigned int 1, int 0, void (void)* 0x5f402a00 `vcall'(void), void * 0x00000000, unsigned int 12, AFX_CMDHANDLERINFO * 0x00000000) line 88CCmdTarget::OnCmdMsg(unsigned int 1, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 302 + 39 bytesCDialog::OnCmdMsg(unsigned int 1, int 0, void * 0x00000000, AFX_CMDHANDLERINFO * 0x00000000) line 97 + 24 bytes CWnd::OnCommand(unsigned int 1, long 656988) line 2088CWnd::OnWndMsg(unsigned int 273, unsigned int 1, long 656988, long * 0x0012f83c) line 1597 + 28 bytesCWnd::WindowProc(unsigned int 273, unsigned int 1, long 656988) line 1585 + 30 bytesAfxCallWndProc(CWnd * 0x0012fe74 {CDebugDlg hWnd=?}, HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 215 + 26 bytesAfxWndProc(HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 368AfxWndProcBase(HWND__ * 0x001204b0, unsigned int 273, unsigned int 1, long 656988) line 220 + 21 bytesUSER32! 77d48709()USER32! 77d487eb()USER32! 77d4b368()USER32! 77d4b3b4()NTDLL! 7c90eae3()USER32! 77d4b7ab()USER32! 77d7fc9d()USER32! 77d76530()USER32! 77d58386()USER32! 77d5887a()USER32! 77d48709()USER32! 77d487eb()USER32! 77d489a5()USER32! 77d489e8()USER32! 77d6e819()USER32! 77d65ce2()CWnd::IsDialogMessageA(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 182 CWnd::PreTranslateInput(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 3424 CDialog::PreTranslateMessage(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 92 CWnd::WalkPreTranslateTree(HWND__ * 0x001204b0, tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 2667 + 18 bytesCWinThread::PreTranslateMessage(tagMSG * 0x004167d8 {msg=0x00000202 wp=0x00000000 lp=0x000f001c}) line 665 + 18 bytesCWinThread::PumpMessage() line 841 + 30 bytesCWnd::RunModalLoop(unsigned long 4) line 3478 + 19 bytes CDialog::DoModal() line 536 + 12 bytesCDebugApp::InitInstance() line 59 + 8 bytesAfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ *0x00000000, char * 0x00141f00, int 1) line 39 + 11 bytes WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x00141f00, int 1) line 30WinMainCRTStartup() line 330 + 54 bytesKERNEL32! 7c816d4f()这里,CDebugDialog::OnOK作为整个调用链中最后被调用的函数出现在call stack的最上方,而内核中程序的启动函数Kernel32! 7c816d4f()则作为栈底出现在最下方。
queue使用方法Queue(队列)是一种常用的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。
在计算机科学中,队列被广泛应用于各种算法和程序中,例如操作系统调度、网络通信、图像处理等。
本文将介绍如何使用队列,包括队列的基本操作、队列的实现方式以及队列的应用场景。
一、队列的基本操作1. 入队(Enqueue):将元素添加到队列的尾部。
新元素总是被添加到队列的末尾,因此队列的尾部指针会随之移动。
2. 出队(Dequeue):从队列的头部移除一个元素,并返回该元素的值。
被移除的元素总是队列的第一个元素,因此队列的头部指针会随之移动。
3. 获取队首元素(Front):返回队列的头部元素的值,但不修改队列。
4. 获取队列大小(Size):返回队列中元素的个数。
5. 判断队列是否为空(IsEmpty):若队列中没有元素,则返回真;否则返回假。
二、队列的实现方式1. 数组实现:使用数组来存储队列的元素,并通过一个指针来标记队列的头部和尾部。
当队列满时,无法再添加新元素;当队列为空时,无法执行出队操作。
数组实现的队列在空间上有一定的限制。
2. 链表实现:使用链表来存储队列的元素,每个节点包含一个数据项和一个指向下一个节点的指针。
链表实现的队列没有空间限制,可以动态地添加或删除元素。
三、队列的应用场景1. 网络通信:队列可以用来缓存待发送的数据包,保证数据的顺序性和可靠性。
2. 操作系统调度:操作系统使用队列来管理进程或线程的调度顺序,保证公平性和响应性。
3. 图像处理:在图像处理中,队列常用于处理像素点或图像的扫描、滤波、变换等操作。
4. 多线程编程:队列可以用于线程之间的数据传输和同步,实现线程安全的操作。
5. 任务处理:队列可以用于任务的排队和执行,保证任务按顺序进行。
在实际应用中,我们可以根据具体的需求选择合适的队列实现方式。
如果对空间要求较高且队列大小固定,可以选择数组实现;如果对空间要求较松散或队列大小不确定,可以选择链表实现。
STL六⼤组件容器(Container)算法(Algorithm)迭代器(Iterator)仿函数(Function object)适配器(Adaptor)空间配置器(allocator)1、容器作为STL的最主要组成部分--容器,分为向量(vector),双端队列(deque),表(list),队列(queue),堆栈(stack),集合(set),多重集合(multiset),映射(map),多重映射(multimap)。
容器特性所在头⽂件<vector>向量vector可以⽤常数时间访问和修改任意元素,在序列尾部进⾏插⼊和删除时,具有常数时间复杂度,对任意项的插⼊和删除就有的时间复杂度与到末尾的距离成正⽐,尤其对向量头的添加和删除的代价是惊⼈的⾼的<deque>双端队列deque基本上与向量相同,唯⼀的不同是,其在序列头部插⼊和删除操作也具有常量时间复杂度<list>表list对任意元素的访问与对两端的距离成正⽐,但对某个位置上插⼊和删除⼀个项的花费为常数时间。
<queue>队列queue插⼊只可以在尾部进⾏,删除、检索和修改只允许从头部进⾏。
按照先进先出的原则。
<stack>堆栈stack堆栈是项的有限序列,并满⾜序列中被删除、检索和修改的项只能是最近插⼊序列的项。
即按照后进先出的原则<set>集合set由节点组成的红⿊树,每个节点都包含着⼀个元素,节点之间以某种作⽤于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序,具有快速查找的功能。
但是它是以牺牲插⼊删除操作的效率为代价的<set>多重集合multiset和集合基本相同,但可以⽀持重复元素具有快速查找能⼒<map>映射map由{键,值}对组成的集合,以某种作⽤于键对上的谓词排列。
具有快速查找能⼒<map>多重集合multimap⽐起映射,⼀个键可以对应多了值。
c语言queue函数用法C语言中的queue函数是一个非常有用的数据结构,用于表示先进先出(FIFO)的队列。
它被广泛应用于许多领域,例如操作系统、网络通信和计算机游戏等。
在本文中,我们将介绍C语言queue函数的详细用法,希望能够帮助初学者更好地掌握这个工具。
首先,我们需要了解queue函数的基本语法。
在C语言中,queue函数是作为一个标准库函数来实现的。
要使用它,我们需要包含“<queue.h>”头文件,并使用“queue”类型来定义一个队列变量。
例如:#include <queue.h>queue<int> myQueue;在这里,我们定义了一个名为“myQueue”的整型队列。
请注意,<queue.h>头文件也提供了对其他类型(如字符、浮点数等)的队列支持。
接下来,我们将介绍queue函数的常用操作。
与其他数据结构一样,队列的主要操作包括入队(push)、出队(pop)、获取队首元素(front)和队列是否为空(empty)。
以下示例代码将演示如何使用这些操作:// 将数字1-5添加到队列中for(int i=1; i<=5; i++) {myQueue.push(i);}// 输出队列的大小cout << "队列大小:" << myQueue.size() << endl;// 弹出队首元素并输出cout << "队首元素:" << myQueue.front() << endl; myQueue.pop();// 队列是否为空if (myQueue.empty()) {cout << "队列为空" << endl;}在这个例子中,我们首先使用push操作将数字1-5添加到队列中。
栈与队列实现先进先出和后进先出的数据结构数据结构是计算机科学中一门重要的基础课程,其中栈(Stack)和队列(Queue)是常用的数据结构。
栈和队列都具有不同的特点和应用场景,能够满足先进先出(FIFO)和后进先出(LIFO)的要求。
一、栈的实现先进先出栈是一种线性数据结构,具有后进先出(LIFO)的特点。
在栈中,只能在栈的一端进行操作,称为栈顶。
栈的基本操作包括入栈(Push)和出栈(Pop)。
1. 入栈(Push)操作:当要向栈中添加元素时,将新元素放置在栈顶,并将栈顶指针向上移动一位。
该操作保证了后添加的元素会处于栈顶的位置。
2. 出栈(Pop)操作:当要从栈中移除元素时,将栈顶的元素弹出,并将栈顶指针向下移动一位。
该操作保证了最后添加的元素会最先被移除。
栈的实现可以使用数组或链表来存储元素。
使用数组实现时,需要指定栈的最大容量。
使用链表实现时,栈的容量可以动态扩展。
二、队列的实现先进先出队列是一种线性数据结构,具有先进先出(FIFO)的特点。
在队列中,元素从队尾入队,从队头出队。
队列的基本操作包括入队(Enqueue)和出队(Dequeue)。
1. 入队(Enqueue)操作:当要向队列中添加元素时,将新元素放置在队尾,并将队尾指针向后移动一位。
该操作保证了后添加的元素会处于队列的尾部。
2. 出队(Dequeue)操作:当要从队列中移除元素时,将队头的元素弹出,并将队头指针向后移动一位。
该操作保证了最早添加的元素会最先被移除。
队列的实现也可以使用数组或链表。
与栈不同的是,队列的实现更适合使用链表,因为链表可以实现在队头和队尾高效地执行插入和删除操作。
三、使用栈和队列实现先进先出和后进先出为了实现先进先出和后进先出的数据结构,可以使用一种特殊的数据结构:双端队列(Double-ended Queue),也称为双端栈(Deque)。
双端队列具有栈和队列的特点,既可以在队尾插入和删除元素,也可以在队头插入和删除元素。
c语⾔stack(栈)和heap(堆)的使⽤详解⼀、预备知识—程序的内存分配⼀个由C/C++编译的程序占⽤的内存分为以下⼏个部分1、栈区(stack)—由编译器⾃动分配释放,存放函数的参数值,局部变量的值等。
其操作⽅式类似于数据结构中的栈。
2、堆区(heap)—⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配⽅式倒是类似于链表。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在⼀块的,初始化的全局变量和静态变量在⼀块区域,未初始化的全局变量和未初始化的静态变量在相邻的另⼀块区域。
程序结束后由系统释放。
4、⽂字常量区—常量字符串就是放在这⾥的。
程序结束后由系统释放。
5、程序代码区—存放函数体的⼆进制代码。
⼆、例⼦程序复制代码代码如下://main.cppint a=0; //全局初始化区char *p1; //全局未初始化区main(){intb;栈char s[]="abc"; //栈char *p2; //栈char *p3="123456"; //123456\0在常量区,p3在栈上。
static int c=0; //全局(静态)初始化区p1 = (char*)malloc(10);p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1,"123456"); //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成⼀个地⽅。
}三、堆和栈的理论知识2.1申请⽅式stack:由系统⾃动分配。
例如,声明在函数中⼀个局部变量int b;系统⾃动在栈中为b开辟空间heap:需要程序员⾃⼰申请,并指明⼤⼩,在c中⽤malloc函数如p1=(char*)malloc(10);在C++中⽤new运算符如p2=(char*)malloc(10);但是注意p1、p2本⾝是在栈中的。
c中queue的用法下面小编就跟你们详细介绍下c中queue的用法的用法,希望对你们有用。
c中queue的用法的用法如下:Model------------------------------------------------------------------------------------------------------------------------队列也是限制插入和删除位置的表.主要操作是enqueue和dequeue操作.enqueue:入队操作.在表的队尾(rear)插入一个元素.dequeue:出队操作.删除表的队首(front)元素.本文使用循环数组实现GenericQueue.需要指定capacity.缺点是超出容量,无法动态增长.当然,可以仿照list的方式克服这个问题.完整代码详见我的github(https:///gnudennis/ds_c)(genric-queue.h generic-queue.c generic-queue-test.c)核心代码------------------------------------------------------------------------------------------------------------------------0. Generic Queue定义[cpp] view plain copy01.typedef void *ElementAddr;02.typedef void (*PfCbFree)(ElementAddr);03.04.typedef struct QueueRecord05.{06. ElementAddr *array;07. int capacity;08. int elemsize;09. int front;10. int rear;11. int size;12. PfCbFree freefn;13.} *Queue;1. API[cpp] view plain copy01./* Create a new queue */02.Queue queue_create(int elemsize, int capacity, PfCbFree freefn);03.04./* Dispose the queue */05.void queue_dispose(Queue que);06.07./* Make the give queue empty */08.void queue_make_empty(Queue que);09.10./* Return true if the queue is empty */11.int queue_is_empty(Queue que);12.13./* Return true if the queue is full */14.int queue_is_full(Queue que);15.16./* Insert a new element onto queue */17.void queue_enqueue(Queue que, ElementAddr elemaddr);18.19./* Delete the front element off the queue */20.void queue_dequeue(Queue que);21.22./* Fetch the front element from the queue */23.void queue_front(Queue que, ElementAddr elemaddr);24.25./* Fetch and Delete the front element from the queue */26.void queue_front_and_dequeue(Queue que, ElementAddr elemaddr);2.Implementation[cpp] view plain copy01./* Create a new queue with capacity */02.Queue03.queue_create(int elemsize, int capacity, PfCbFree freefn)04.{05. Queue que;06.07. que = malloc(sizeof(struct QueueRecord));08. if ( que == NULL ) {09. fprintf(stderr, "Out of memory\n");10. exit(1);11. }12.13. que->elemsize = elemsize;14. que->capacity = capacity > MIN_QUEUE_SIZE ? capacity : MIN_QUEUE_SIZE;15.16. que->array = malloc(elemsize * que->capacity);17. if ( que->array == NULL ) {18. fprintf(stderr, "Out of memory\n");19. exit(1);20. }21. que->front = 1;22. que->rear = 0;24. que->freefn = freefn;25.26. return que;27.}28.29./* Dispose the queue */30.void31.queue_dispose(Queue que)32.{33. if (que != NULL) {34. queue_make_empty(que);35. free(que->array);36. free(que);37. }38.}39.40./* Make the give queue empty */41.void42.queue_make_empty(Queue que)43.{44. if ( que->freefn ) {45. int i;46. for ( i = 0; i < que->size; ++i) {47. free((char *)que->array +48. que->elemsize * i);49. }50. }51. que->size = 0;52. que->front = 1;54.}55.56./* Return true if the queue is empty */57.int58.queue_is_empty(Queue que)59.{60. return que->size == 0;61.}62.63./* Return true if the queue is full */64.int65.queue_is_full(Queue que)66.{67. return que->size == que->capacity;68.}69.70.static int71.successor(Queue que, int index)72.{73. if ( ++index == que->capacity)74. index = 0;75. return index;76.}77.78./* Insert a new element onto queue(rear) */79.void80.queue_enqueue(Queue que, ElementAddr elemaddr)81.{82. void *target;83.84. if ( queue_is_full(que) ) {85. fprintf(stderr, "Full queue\n");86. exit(1);87. }88. que->rear = successor(que, que->rear);89. target = (char *)que->array + que->elemsize * que->rear;90. memcpy(target, elemaddr, que->elemsize);91. que->size++;92.}93.94./* Delete the front element off the queue */95.void96.queue_dequeue(Queue que)97.{98. if ( queue_is_empty(que) ) {99. fprintf(stderr, "Empty queue\n");100. exit(1);101. }102. if ( que->freefn ) {103. void *target = (char *)que->array +104. que->front * que->elemsize;105. que->freefn(target);106. }107. que->size--;108. que->front = successor(que, que->front);109.}110.111./* Fetch the front element from the queue */112.void113.queue_front(Queue que, ElementAddr elemaddr)114.{115. void *target = (char *)que->array +116. que->front * que->elemsize;117. memcpy(elemaddr, target, que->elemsize);118.}119.120./* Fetch and Delete the front element from the queue */ 121.void122.queue_front_and_dequeue(Queue que, ElementAddr elemaddr)123.{124. void *target;125.126. if ( queue_is_empty(que) ) {127. fprintf(stderr, "Empty queue\n");128. exit(1);129. }130.131. target = (char *)que->array +132. que->front * que->elemsize;133. memcpy(elemaddr, target, que->elemsize);134.135. que->size--;136. que->front = successor(que, que->front);137.}分析----------------本文使用循环数组实现GenericQueue.需要指定capacity.既然是循环数组,就是围成一个圈.也就插入第一个元素没有必要非要放在0处啦.初始状态:{que->size = 0;que->front = 1;que->rear = 0;}说明这样第一次enqueue操作放在array[1]处,当然:这不是必须的,取决于你想放在那里.#define mxx{que->size = 0;que->front =m+1;que->rear = m;}就放在array[m+1]处.。
STL--stack/queue的使用方法2010-01-0517:36stack(栈)和queue(队列)也是在程序设计中经常会用到的数据容器,STL为我们提供了方便的stack(栈)的queue(队列)的实现。
准确地说,STL中的stack和queue不同于vector、list等容器,而是对这些容器的重新包装。
这里我们不去深入讨论STL的stack和queue的实现细节,而是来了解一些他们的基本使用。
1、stackstack模板类的定义在<stack>头文件中。
stack模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型为deque。
定义stack对象的示例代码如下:stack<int>s1;stack<string>s2;stack的基本操作有:入栈,如例:s.push(x);出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()2、queuequeue模板类的定义在<queue>头文件中。
与stack模板类很相似,queue模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型。
定义queue对象的示例代码如下:queue<int>q1;queue<double>q2;queue的基本操作有:入队,如例:q.push(x);将x接到队列的末端。
出队,如例:q.pop();弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()3、priority_queue在<queue>头文件中,还定义了另一个非常有用的模板类priority_queue(优先队列)。
优先队列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。
priority_queue模板类有三个模板参数,第一个是元素类型,第二个容器类型,第三个是比较算子。
其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大的往后排(出队时序列尾的元素出队)。
定义priority_queue对象的示例代码如下:priority_queue<int>q1;priority_queue<pair<int,int>>q2;//注意在两个尖括号之间一定要留空格。
priority_queue<int,vector<int>,greater<int>>q3;//定义小的先出队priority_queue的基本操作与queue相同。
初学者在使用priority_queue时,最困难的可能就是如何定义比较算子了。
如果是基本数据类型,或已定义了比较运算符的类,可以直接用STL的less算子和greater 算子——默认为使用less算子,即小的往前排,大的先出队。
如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:重载比较运算符。
优先队列试图将两个元素x和y代入比较运算符(对less算子,调用x<y,对greater算子,调用x>y),若结果为真,则x排在y前面,y将先于x出队,反之,则将y排在x前面,x将先出队。
看下面这个简单的示例:#include<iostream>#include<queue>using namespace std;class T{public:int x,y,z;T(int a,int b,int c):x(a),y(b),z(c){}};bool operator<(const T&t1,const T&t2){return t1.z<t2.z;//按照z的顺序来决定t1和t2的顺序}main(){priority_queue<T>q;q.push(T(4,4,3));q.push(T(2,2,5));q.push(T(1,5,4));q.push(T(3,3,6));while(!q.empty()){T t=q.top();q.pop();cout<<t.x<<""<<t.y<<""<<t.z<<endl;}return1;}输出结果为(注意是按照z的顺序从大到小出队的):336225154443再看一个按照z的顺序从小到大出队的例子:#include<iostream>#include<queue>using namespace std;class T{public:int x,y,z;T(int a,int b,int c):x(a),y(b),z(c){}};bool operator>(const T&t1,const T&t2){return t1.z>t2.z;}main(){priority_queue<T,vector<T>,greater<T>>q;q.push(T(4,4,3));q.push(T(2,2,5));q.push(T(1,5,4));q.push(T(3,3,6));while(!q.empty()){T t=q.top();q.pop();cout<<t.x<<""<<t.y<<""<<t.z<<endl;}return1;}输出结果为:443154225336如果我们把第一个例子中的比较运算符重载为:bool operator<(const T&t1,const T&t2){return t1.z>t2.z;//按照z的顺序来决定t1和t2的顺序}则第一个例子的程序会得到和第二个例子的程序相同的输出结果。
1.6nth_element指定元素排序nth_element一个容易看懂但解释比较麻烦的排序。
用例子说会更方便:班上有10个学生,我想知道分数排在倒数第4名的学生。
如果要满足上述需求,可以用sort排好序,然后取第4位(因为是由小到大排),更聪明的朋友会用partial_sort,只排前4位,然后得到第4位。
其实这是你还是浪费,因为前两位你根本没有必要排序,此时,你就需要nth_element:template<class RandomAccessIterator>void nth_element(RandomAccessIterator first,RandomAccessIterator nth, RandomAccessIterator last);template<class RandomAccessIterator,class StrictWeakOrdering>void nth_element(RandomAccessIterator first,RandomAccessIterator nth, RandomAccessIterator last,StrictWeakOrdering comp);对于上述实例需求,你只需要按下面要求修改1.4中的程序:stable_sort(vect.begin(),vect.end(),less<student>());替换为:nth_element(vect.begin(),vect.begin()+3,vect.end(),less<student>());运行结果为:------before sort...Tom:74Jimy:56Mary:92Jessy:85Jone:56Bush:52Winter:77Andyer:63Lily:76Maryia:89-----after sort....Jone:56Bush:52Jimy:56Andyer:63Jessy:85Mary:92Winter:77Tom:74Lily:76Maryia:89第四个是谁?Andyer,这个倒霉的家伙。
为什么是begin()+3而不是+4?我开始写这篇文章的时候也没有在意,后来在ilovevc的提醒下,发现了这个问题。
begin()是第一个,begin()+1是第二个,...begin()+3当然就是第四个了。