zoukankan      html  css  js  c++  java
  • 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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    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)程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。

  • 相关阅读:
    【转】JVM 堆内存设置原理
    【转】Java八种基本数据类型的比较及其相互转化
    8月12日
    并发与竞争
    高通gpio配置输出
    创建一个字符设备的基本流程
    4月2号 字符设备驱动实验
    3.30学习遇到卡死点
    断言函数的用法
    12.02 下午
  • 原文地址:https://www.cnblogs.com/Kobe10/p/5567232.html
Copyright © 2011-2022 走看看