TZOJ 7871:维护序列 单链表应用(创建/查询/插入/删除)
描述
给定一个长度为n的整数序列。现在有m个操作,操作分为三类,格式如下:
(1) 1 i:询问序列中第i个元素的值,保证i小于等于当前序列长度。
(2) 2 i v:在序列中第i个元素前加入新的元素v,保证i小于等于当前序列长度。
(3) 3 i:删除序列中的第i个元素,保证i小于等于当前序列长度。
输入
第1行输入n(1<=n<=1000),表示序列最初的长度;
第2行输入n个空格隔开的数,表示原始的整数序列;
第3行输入m(1<=m<=1000),表示操作数;
第4到m+3行依次输入一个操作。
输出
对于操作(1)输出对应的答案,一行输出一个数。
样例输入
5
6 31 23 14 5
5
1 2
2 2 7
1 2
3 3
1 3
样例输出
31
7
23
搞了蛮久的,不懂指针变量之间的应用,总是处理不好头指针head会被改变的情况,不过最后参照着创建函数cl直接返回一个node类型的指针给head,达到了插入和删除都能更新头指针head的效果,才解决了
链表总体来说是一个很具象化的东西,关于链表的创建/遍历查询/删除/插入都可以通过正常的思维来得出具体的操作过程,只需要记住对于一个链表的元素, 它只有数据和指向下一个元素的指针地址就够了。
#include<bits/stdc++.h> using namespace std; struct node{ int data; struct node *next; }; int n,m; node* cl(int n)//构造链表 { node *s,*head,*r; s = new node; //创建一个新节点 head = s; //记录首节点地址 int i,num; cin>>num; s->data = num; //构建第一个节点的值和下一节点的地址 s->next = NULL; r = s; //将构建好的节点s存到r中 for(i=0;i<n-1;i++) { cin>>num; s = new node; s->data = num; //将输入存储到新节点s中 r->next = s; //将上一节点r的next和s链接 r = s; //r继承当前节点s } r->next = NULL; //当前最新节点指向空,标志链表结束 return head; //返回链表头部地址 } void find(node *head,int i)//查询 { node *s,*r; s = head; //先让s成为头节点 while(i--) { s= s->next; //将当前s的下一个节点next作为新的节点s } cout<<s->data<<endl; } node* insert(node *head,int i,int v)//插入 { node *s,*r; s = head; r = new node; r->data = v; if(i==-1){ //元素要插入成为第一个 r->next = s; //让当前元素r的地址指向头指针,并以r为头指针返回 return r; } while(i--) s = s->next; //找到元素i的前一位 r->next = s->next;//让元素r的下一位和当前元素s的下一位链接 s->next = r; //当前元素s的下一位改为链接r,就实现了插入 return head; //正常返回头指针 } node* del(node *head,int i) //删除元素,返回头指针 { node *s,*r; s = head; r = new node; if(i==-1){ //删除头指针 return head->next; //返回头指针的下一个元素地址 } while(i--)s = s->next; //找到第i个元素的前一个元素 s->next = s->next->next; //将元素i的前一个元素s的下一个链接修改为下下个,跳过第i个元素,达到删除的效果 return head; } int main() { cin>>n; node *head = cl(n); cin>>m; while(m--) { int k,i,v; //操作k,下标i,数值v cin>>k; if(k==1) { cin>>i; find(head,i-1);//下标i-1方便while(i--)索引第i个元素 } else if(k==2){ cin>>i>>v; head = insert(head,i-2,v);//下标i-2方便while(i--)索引第i-1个元素 } else{ cin>>i; head = del(head,i-2); } } return 0; }