C++面试笔记--循环链表,队列,栈,堆

之前已经学会了单链表的建立删除插入转置以及一些普通操作,双链表和单链表差不多,就是多了一个前驱指针,在许多操作中很方便,但是加了一个指针开销应该会大一些,总体上影响不大,这里开始讨论循环链表以及其他的一些数据结构。

1、已知n个人(以编号1,2,3,...,n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,他的下一个人又从k开始报数,数到m的那个人出列,依次重复下去,直到圆桌的人全部出列。试用C++编写实现。

解析:本题就是约瑟夫环问题的实际场景,要通过输入n、m、k三个正整数,求出列的序列。这个问题采用的是典型的循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素:

p->link=head;

解决问题的核心步骤如下:

(1)建立一个具有n个链节点、无头节点的循环链表。

(2)确定第一个报数人的位置。

(3)不断的从链表中删除链节点,直到链表为空。

答案:

    

 1 #include<iostream>
 2 using namespace std;
 3 typedef struct LNode
 4 {
 5     int data;
 6     struct LNode *link;
 7 }LNode,*LinkList;
 8 //n为总人数,k为第一个开始报数的人,m为出列者喊到的数
 9 void JOSEPHUS(int n,int k,int m)
10 {
11     //p为当前节点,r为辅助节点,指向p的前驱节点,list为头节点    LinkList p,r,list,curr;
12
13     //简历循环链表    p=(LinkList)malloc(sizeof(LNode));
14     p->data=1;
15     p->link=p;
16     curr=p;
17     for(int i=2;i<=n;i++)
18     {
19         LinkList t=(LinkList)malloc(sizeof(LNode));
20         t->data=i;
21         t->link=curr->link;
22         curr->link=t;
23         curr=t;
24     }
25     //把当前指针移动到第一个报数的人
26     r=curr;
27     while(k--)
28         r=p,p=p->link;
29     while(n--)
30     {
31         for(int s=m-1;s--;r=p,p=p->link);
32         r->link=p->link;
33         printf("%d->",p->data);
34         free(p);
35         p=r->link;
36     }
37 }

2、编程实现队列的入队/出队操作。

答案:

    

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4
 5 const int MaxQueueSize=100;
 6 class Queue{
 7 private:
 8     int front; //指向头结点
 9     int rear; //指向最后一个元素的下一结点
10     //int *base;//用于动态分配内存,pBase保存数组的首地址
11     int queues[MaxQueueSize];
12 public:
13     Queue();
14     ~Queue();
15     bool isEmpty();
16     bool isFull();
17     void enQueue(const int &item);
18     int outQueue(void);
19 };
20 Queue::Queue(){
21     front=0;
22     rear=0;
23 }
24 Queue::~Queue(){
25     front=0;
26     rear=0;
27 }
28 void Queue::enQueue(const int &item){
29     if(!isFull()){
30         queues[rear]=item;
31         rear++;
32     }
33     else
34         cout<<"队列已满!!"<<endl;
35 }
36 int Queue::outQueue(void){
37     if(!isEmpty()){
38         int value=queues[front];
39         return value;
40         front++;
41     }
42     else
43         cout<<"队列已空!!"<<endl;
44 }
45 bool Queue::isEmpty(){
46     if(rear==front)
47         return true;
48     else
49         return false;
50 }
51 bool Queue::isFull(){
52     return rear > MaxQueueSize?true:false;
53 }

3、用两个栈实现一个队列的功能,请用C++实现。

解析:思路如下:

假设两个栈A和B,且都为空。

可以认为栈A提供入队列的功能,栈B提供出队列的功能。

入队列:入栈A。

出队列:

(1)如果栈B不为空,直接弹出栈B的数据。

(2)如果栈B为空,则依次弹出栈A的数据,放入栈B中,再弹出栈B的数据。

答案:

    

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<stdlib.h>
 4 #include<stack>
 5 using namespace std;
 6 /*
 7         思路:1.从头到尾遍历一遍链表,利用for循环进行遍历把遍历的数据存入到栈中
 8               2.利用栈的数据结构进行输出,递归的输出
 9 */
10 typedef struct ListNode{//链表的结构
11     int m_nKey;
12     ListNode *m_pNext;
13 }node;
14
15         //利用栈进行输出
16 int printlianbiao(ListNode *pHead){//
17     std::stack<ListNode*> nodes;//构造一个储存泛型的栈,存储的是链表数据
18     ListNode* pNode=pHead;
19     while(pNode!=NULL){
20         nodes.push(pNode);//进栈
21         pNode=pNode->m_pNext;//一个节点的后继
22     }
23     //从栈中输出这些数据
24     while(!nodes.empty()){
25         pNode=nodes.top();//头指针指向栈顶
26         cout<<pNode->m_nKey<<endl;;//输出栈顶的值
27         nodes.pop();//出站
28     }
29 }
30         //利用递归进行输出
31         /*      1.递归的输出链表中的数
32                 2.递归的先输出前面的数
33         */
34 int printdigui(ListNode *pHead){
35     if(pHead!=NULL){
36         if(pHead->m_pNext!=NULL){
37             printdigui(pHead->m_pNext);
38         }
39         cout<<pHead->m_nKey<<endl;
40     }
41 }
42 node *creat(){//创建链表
43     node *head,*p,*s;
44     head=(node *)malloc(sizeof(node));//申请动态内存
45     p=head;
46     int x,cycle=1;
47     while(cycle){
48 //        cout<<"请输入数据"<<endl;
49         cin>>x;
50         if(x!=-1){
51             s=(node *)malloc(sizeof(node));//为S申请动态内存
52             s->m_nKey=x;
53             p->m_pNext=s;//头指针指向第一个刚刚输入的数据
54             p=s;//头指针移动一位
55         }
56         else
57             cycle=0;
58     }
59     head=head->m_pNext;//头指针指向下一位
60     p->m_pNext=NULL;
61     return head;
62 }
63 int main(){
64     node *pHead=creat();
65     cout<<"利用栈进行输出"<<endl;
66     printlianbiao(pHead);
67     cout<<"利用递归进行输出"<<endl;
68     printdigui(pHead);
69
70 }

4、请讲诉heap和stack的差别。

解析:在进行C/C++编程时,需要程序员对内存的了解比较精准。经常需要操作的内存可分为以下几个类别:

(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。

(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表

(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域。程序结束后由系统释放。

(4)文字常量区:常量字符串就是放在这里的,程序结束后由系统释放。

(5)程序代码区:存放函数体的二进制代码。

答案:

(1)stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。

(2)stack空间有限,heap是很大的自由存储区。

(3)C中的malloc函数分配内存空间即在堆上,C++中对应的是new操作符。

(4)程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。

时间: 2024-08-26 05:10:12

C++面试笔记--循环链表,队列,栈,堆的相关文章

java课堂笔记------Map,队列,栈

* java.util.Map * Map看起来像是一个多行两列的表格 * 每条记录分为两部分:key,value * 其中在一个Map中key是不允许重复的.(equals比较) * * 常用的实现类:java.util.HashMap(散列算法实现) * TreeMap(二叉树实现) Map<String,Integer> map = new HashMap<String,Integer>(); * V put(K k,V v) * 将给定的key与value存入到Map中.

算法笔记2-优先队列(堆)(上)

一.什么是优先队列? 看一情景:我们去KTV唱歌,点歌的时候,可以发现所点的歌就是一个队列. 这时候,一个MM突然不玩手机了想唱歌,于是她来点歌,并且想尽早轮到她. 于是她可以选择"插歌"这个功能插到前排队列里. 这种具备可以插入优先权元素的队列,就叫优先队列.但是,这个定义不是严谨的. 优先队列的基本模型是这样的-- 具备两个功能: insert插入: deleteMin 删除最小者. 它的工作就是-- 它很有用哦,具体可以用在操作系统,外部排序和贪婪算法中等. 二.怎么实现优先队列

转---队列、堆、栈、堆栈的区别

队列.堆.栈.堆栈的区别 堆栈:先进后出(就像放在箱子的衣服,先放进去的后拿出来) 队列:先进先出(就像一条路,有一个入口和一个出口,先进去的就可以先出去) 进程中每个线程都有自己的堆栈,这是一段线程创建时保留下的地址区域.我们的"栈内存"即在此. 至于"堆"内存,我个人认为在未用new定义时,堆应该就是未"保留"未"提交"的自由空间,new的功能是在这些自由空间中保留(并提交)出一个地址范围. 栈(Stack)是操作系统在建

STL源码笔记(15)—堆和优先级队列(二)

STL源码笔记(15)-堆和优先级队列 优先级队列的源码实现基于heap的操作,底层容器默认是vector. 优先级队列简介 优先级队列跟队列类似,一端插入一端删除,不同的是,优先级队列的元素入队后会根据其优先级进行调整,默认情况下优先级高的将优先出队,在SGI STL中,优先级队列的功能保证由heap实现:stl_heap.h中,heap的分析见:STL堆源码分析 优先级队列构造函数 默认情况下,优先级队列使用vector作为底层容器,使用less作为比较函数,其在源码中的定义声明如下: te

STL源码笔记(14)—堆和优先级队列(一)

STL源码笔记(14)-堆和优先级队列 priority_queue是拥有权值观念的queue,跟queue类似,其只能在一端push,一端pop,不同的是,每次push元素之后再容器内部元素将按照一定次序排列,使得pop得到的元素始终是当前权值的极大值. 很显然,满足这个条件就需要某些机制了,缺省情况下使用max-heap大顶堆来实现,联想堆排序的实现,使用大顶完成序列从小到大的排序,过程大概是: 把堆的根元素(堆中极大值)交换到最后 堆的长度减1 这样每次取出堆中的极大值完成排序,刚好与优先

5、蛤蟆的数据结构笔记之五链栈实现

5.蛤蟆的数据结构笔记之五链栈实现 本篇名言:"人生就像奕棋,一步失误,全盘皆输." 昨天对栈和队列进行了定义.这次我们来看下如何使用代码来实现链栈和链队列,后续蛤蟆会记录如何将栈应用到实际问题中. 栈一般是顺序结构,但是也可以采用链式存储结构,具体如下实现. 欢迎转载,转载请标明出处: 1.  定义结构体 #define MAX_STACKS10 typedef struct { intkey; /*otherfields */ }element; typedef struct st

常量池 栈 堆

Java内存分配: 1. 寄存器:我们在程序中无法控制 2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 3. 堆:存放用new产生的数据 4. 静态域:存放在对象中用static定义的静态成员 5. 常量池:存放常量 6. 非RAM存储:硬盘等永久存储空间 --------------------------------------------------------------------------------------------------------

Android自学笔记-16-任务栈

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2170 贴个baka爷的代码留念.. 数据出的有问题,输入的字符串长度不超过1000 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #incl

python[数据]--队列,堆,优先级队列

队列:from collections import deque:实现保存最后几条历史记录,list = deque(maxlen=6),那么超过六条记录会删除之前的记录. 堆:import heapq;最大特点是第一弹出的元素总是堆中最小的元素:list=[1,2,3] heap=heapq.heapify(list) ,nlargest(3,数据,key=lambda) nsmallest() 优先级队列:堆中的元素(-优先级,序号,item)这样即可实现优先级,优先级越高最先pop出堆,优