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

  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/Kobe10/p/5567232.html
Copyright © 2020-2023  润新知