【NOI题解】 3.2数据结构之指针和链表
2017-12-21 19:57
295 查看
NOI题目地址(3.2数据结构之指针和链表):http://noi.openjudge.cn/ch0302/
这部分的题解出于练习指针和链表的目的,我都是自定义的链表结构。实际上C++提供了STL list链表容器,对于链表元素的增删查反转等操作都有封装好的接口,直接使用将会得到非常简洁的代码。
用循环链表解决约瑟夫环问题
关键在于:
- 删除链表结点的操作
- 注意对循环链表prev指针的处理
AC题解:
考察单链表的基本操作:插入、删除、遍历
AC题解:
考察单链表的逆置
这里使用的简单循环的方法来进行单链表的逆置。
此外还可以使用回溯或者头插法进行单链表的原地逆置。
参考:
单链表的就地逆置
单链表的逆置–普通循环方法(详细图解)
AC题解
这部分的题解出于练习指针和链表的目的,我都是自定义的链表结构。实际上C++提供了STL list链表容器,对于链表元素的增删查反转等操作都有封装好的接口,直接使用将会得到非常简洁的代码。
1748:约瑟夫问题
分析:用循环链表解决约瑟夫环问题
关键在于:
- 删除链表结点的操作
- 注意对循环链表prev指针的处理
AC题解:
#include <iostream> using namespace std; struct node { int data; node* next; }; node *link_create(int n) { // 创建第一个节点 node *head; node *p = new node(); p->data = 1; head = p; for(int i=2;i<=n;i++) { node *q = new node(); q->data = i; p->next = q; p = q; } p->next = head; return head; } void link_process(node *head, int k,int m) { // 获取第k个节点 node *p = head, *prev = head; // 找到头结点的前一个结点 while(prev->next != head) prev = prev->next; // 找到开始计数位置 while(p->data!=k) p = p->next; // 开始约瑟夫过程 while(p->next != p) { // count++; for(int i=0;i<m-1;i++) { prev = p; p = p->next; } // 删除当前结点 node* del = p; // cout<<"del:"<<del->data<<endl; prev->next = p->next; // the same with: prev->next = prev->next->next; p = prev->next; //下一只猴子从1接着继续数 delete del; } cout<<p->data<<endl; delete p; } int main() { int n,m; while(true) { cin>>n>>m; if(n==0&&m==0) break; node* head = link_create(n); link_process(head,1,m); } return 0; }
6378:删除数组中的元素(链表)
分析:考察单链表的基本操作:插入、删除、遍历
AC题解:
#include <iostream> using namespace std; class node { public: node(){}; //用于头结点这种空Node node(int n_data):data(n_data),next(NULL){}; //用于链表中的元素结点 int data; node* next; }; // 本题每次插入末尾,不会插入之前的序列中,因此不要每次插入时遍历链表,否则会超时 // void link_insert(node* head, int pos, node* p) // { // node* tmp = head; // for(int i=1;i<=pos-1;i++) // { // tmp = tmp->next; // } // tmp->next = p; // } void link_create(node* head) { node *p = head; int n; cin>>n; while(n--) { int data; cin>>data; node *p_new = new node(data); p->next = p_new; p = p_new; } } void link_print(node* head) { node *p = head; while(p->next!=NULL) { p = p->next; cout<<p->data<<" "; } cout<<endl; } void link_delete(node *head, int data) { node *p = head->next; node *prev = head; while(p!=NULL) { if(p->data == data) { //删除该结点 // cout<<"prev->next:"<<prev->data<<" "<<p->next->data<<endl; prev->next = p->next; node *del = p; p = p->next; delete del; }else { prev = p; p = p->next; } } } int main() { // 头指针,指向链表的首个结点 node *head = new node(); link_create(head); // link_print(head); int delData; cin>>delData; link_delete(head,delData); link_print(head); delete head; }
6379:统计学生信息(使用动态链表完成)
分析:考察单链表的逆置
这里使用的简单循环的方法来进行单链表的逆置。
此外还可以使用回溯或者头插法进行单链表的原地逆置。
参考:
单链表的就地逆置
单链表的逆置–普通循环方法(详细图解)
AC题解
#include <iostream> #include <string.h> #include <sstream> using namespace std; struct info { string id; string name; char gender; int age; float score; string address; }; class node { public: node():next(NULL){}; //用于头结点这种空Node node(info n_data):data(n_data),next(NULL){}; //用于链表中的元素结点 info data; node* next; }; // 本题每次插入末尾,不会插入之前的序列中,因此不要每次插入时遍历链表,否则会超时 // void link_insert(node* head, int pos, node* p) // { // node* tmp = head; // for(int i=1;i<=pos-1;i++) // { // tmp = tmp->next; // } // tmp->next = p; // } void link_create(node* head) { node *p = head; while(true) { // 借助stringstream用空格分隔字符串 string command; getline(cin,command); stringstream ss(command); info data; ss>>data.id>>data.name>>data.gender>>data.age>>data.score>>data.address; // cout<<data.id<<" "<<data.name<<" "<<data.gender<<" "<<data.age<<" "<<data.score<<" "<<data.address<<endl; if(data.id=="end") { break; } node *p_new = new node(data); p->next = p_new; p = p_new; } } void link_print(node* head) { node *p = head; while(p->next!=NULL) { p = p->next; cout<<p->data.id<<" "<<p->data.name<<" "<<p->data.gender<<" " <<p->data.age<<" "<<p->data.score<<" "<<p->data.address<<endl; } cout<<endl; } // 普通循环方法逆置带头头结点的单链表 node* link_reverse(node *head) { node *p1 = head->next; node *p2 = head->next->next; p1->next = NULL; //这里特殊处理一下头结点,否则头结点和第一个结点会生成环 node *pnext; while(p2!=NULL) { pnext = p2 -> next; p2 -> next = p1; p1 = p2; p2 = pnext; } node* newHead = new node(); newHead->next = p1; return newHead; } int main() { // 头指针,指向链表的首个结点 node *head = new node(); link_create(head); // link_print(head); node *rLinkHead = link_reverse(head); link_print(rLinkHead); }
相关文章推荐
- 3.2数据结构之指针和链表 1748:约瑟夫问题
- 数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)
- 关于链表、树等数据结构中常见的二级指针
- 数据结构:二级指针与不含表头的单链表
- 数据结构学习记录-两个链表相加之函数指针的运用
- 一步一步学数据结构之1--1(队列--单链表表实现--不含队头尾指针)
- 数据结构——指针仿真链表
- 一步一步学数据结构之1--1(队列--单链表实现--含队头尾指针)
- 数据结构之设置尾指针的单向循环链表(参考整理严蔚敏数据结构)
- 数据结构:链表(指针+游标)
- 【数据结构】C语言实现双向链表(带头尾指针,非循环链表)
- python数据结构学习笔记-2016-10-28-01-带尾指针的链表和排序链表
- 数据结构(队列--单链表表实现--不含队头尾指针)
- python数据结构之链表——移除重复项及带随机指针的链表复制
- 利用C指针编写自己的一些数据结构(链表)
- 数据结构链表 --头指针链表复习
- 数据结构——循环链表、仅设尾指针的循环链表、约瑟夫环
- 数据结构——链表(头指针、头结点)
- 一步一步学数据结构之1--1(队列--单链表实现--含队头尾指针)
- 数据结构 02 链表 一般实现和二级指针的实现