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)程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM