之前已經學會了單鏈表的建立刪除插入轉置以及一些普通操作,雙鏈表和單鏈表差不多,就是多了一個前驅指針,在許多操作中很方便,但是加了一個指針開銷應該會大一些,總體上影響不大,這里開始討論循環鏈表以及其他的一些數據結構。
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)程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行。