标签:
之前已经学会了单链表的建立删除插入转置以及一些普通操作,双链表和单链表差不多,就是多了一个前驱指针,在许多操作中很方便,但是加了一个指针开销应该会大一些,总体上影响不大,这里开始讨论循环链表以及其他的一些数据结构。
解析:本题就是约瑟夫环问题的实际场景,要通过输入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 }
答案:
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 }
解析:思路如下:
假设两个栈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 }
解析:在进行C/C++编程时,需要程序员对内存的了解比较精准。经常需要操作的内存可分为以下几个类别:
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表
(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域。程序结束后由系统释放。
(4)文字常量区:常量字符串就是放在这里的,程序结束后由系统释放。
(5)程序代码区:存放函数体的二进制代码。
答案:
(1)stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。
(2)stack空间有限,heap是很大的自由存储区。
(3)C中的malloc函数分配内存空间即在堆上,C++中对应的是new操作符。
(4)程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行。
标签:
原文地址:http://www.cnblogs.com/Kobe10/p/5567232.html