浅谈单向链表
链表介绍
链表是由节点构成的一条链,每一个节点由两部分组成,一部分存储此节点的信息(数据域),另一部分存储链表后继元素的存储位置(指针域),这两部分合在一起就是一个节点。链表的节点通常用结构体来表示,一个表示数据域,一个表示指针域。
struct Node{ int data; //链表的数据域 Node *next; //链表的指针域(指针类型) };
链表的定义和普通结构体变量的定义是一样的,但是链表是指针变量。
Node *p;
单向链表的基本操作
单向链表是链表的一种,单向链表是从头到尾,只可以单向查询或者寻找。每次查询或者寻找必须从链表的开头开始。下面的图可以直观的了解单向链表结构:
(一)申请、释放存储单元
p=new Node; //申请存储单元 free(s); //释放空间
(二)初始化
链表初始化为NULL,而且链表一般有一个开始的部分head,作为链表的开始,而且一般head中不存放数据,只有一个指向链表第一个元素的指针next。
(三)查找链表在x位置的元素
链表的查询是链表的基本操作之一。具体步骤:从头开始遍历整个链表,找到第x个位置的元素并输出。下面是代码:
void get(int x){ //查找第x个元素 Node *p; //申请指针变量 p=head->next; //从第一个元素开始 int i=1; while((p!=NULL) && (i<x)){ i++; p=p->next; } if(p!=NULL && i==x) printf("%d\n",p->data); //如果满足条件就输出位置 }
因为链表初始化时NULL,所以在while语句的条件中是p!=NULL。要查找第x个元素,while的条件是i<x,而不是i<=x,想想为什么?因为当满足i<x时,还会继续做,等到i=x时,while才会停止。
(四)在链表中查找元素x
在链表中寻找x,依旧要从head开始寻找,具体步骤见一下代码:
①查找元素x在链表中第一次出现的位置
②查找元素x在链表中出现的所有位置
void search1(int x){ //查找x第一次出现的位置 Node *p; p=head->next; int i=1; while(p->data!=x && p->next!=NULL){ p=p->next; i++; } if(p->data==x) printf("%d\n",i); } void search2(int x){ //查找所有x的位置 Node *p; p=head->next; int i=1; while(p->next!=NULL){ //只要没有遍历整个链表,就继续寻找 if(p->data==x) printf("%d ",i); p=p->next; i++; } printf("\n"); }
(四)在元素i之前,插入x
在单向链表中插入元素理解起来还是比较简单的,因为链表的各个部分之间是用指针链接的,在插入的时候只需要修改指针的指向就可以了。下面看一下代码:
void add(int i,int x){ // 在i之前插入x Node *p; p=head; int j=0; while(j<i-1 && p!=NULL){ p=p->next; j++; } if(p!=NULL){ Node *s; s=new Node; //申请新空间 s->data=x; //让s的数据域为x s->next=p->next; //把s接到插入前p的下一个位置 p->next=s; //把s接到p的后面 } }
(五)删除链表中的某个元素
删除链表中的第x个元素和之前的操作一样,也是先从头开始寻找x。在找到x之后,就可以利用与在链表中插入元素类似的方法,删除一个元素。
如上图所示,删除一个元素就是把这个元素的上一部分和下一部分连接,然后释放当前元素的空间。程序如下:
void delete_1(int x){ //删除第x个元素 Node *s,*p; p=head; int i=0; while(p->next!=NULL && i<x-1){ p=p->next; i++; } if(p->next!=NULL){ s=p->next; //把第x个元素取出链表 p->next=p->next->next; //把p下一个的下一个接到p后面 free(s); //释放元素x的空间 } }
(六)求一条链表的长度
求链表的长度只需要从头到尾遍历一遍链表就OK啦!非常的简单哦,就不做过多的解释了,代码如下:
void len(){ //输出链表的长度 Node *p; p=head; int i=0; while(p!=NULL){ ++i; p=p->next; } printf("%d\n",i-1); }
总结
单向链表的基础操作差不多就介绍完了,下面附上一个完整的单向链表基础操作代码:
#include<bits/stdc++.h> using namespace std; struct Node{ int data; Node *next; }; Node *head,*r; int n,q,m; void search1(int x){ Node *p; p=head->next; int i=1; while(p->data!=x && p->next!=NULL){ p=p->next; i++; } if(p->data==x) printf("%d\n",i); } void search2(int x){ Node *p; p=head->next; int i=1; while(p->next!=NULL){ if(p->data==x) printf("%d ",i); p=p->next; i++; } printf("\n"); } void get(int x){ Node *p; p=head->next; int i=1; while((p!=NULL) && (i<x)){ i++; p=p->next; } if(p!=NULL && i==x) printf("%d\n",p->data); } void add(int i,int x){ Node *p; p=head; int j=0; while(j<i-1 && p!=NULL){ p=p->next; j++; } if(p!=NULL){ Node *s; s=new Node; s->data=x; s->next=p->next; p->next=s; } } void delete_1(int x){ Node *s,*p; p=head; int i=0; while(p->next!=NULL && i<x-1){ p=p->next; i++; } if(p->next!=NULL){ s=p->next; p->next=p->next->next; free(s); } } void len(){ Node *p; p=head; int i=0; while(p!=NULL){ ++i; p=p->next; } printf("%d\n",i-1); } int main(){ Node *p; int i,j,x; cin>>n>>m; head=new Node; r=head; for(i=1;i<=n;i++){ p=new Node; cin>>x; p->data=x; p->next=NULL; r->next=p; r=p; } for(i=1;i<=m;i++){ cin>>q; if(q==1){ cin>>x; get(x); } else if(q==2){ cin>>x; search1(x); } else if(q==3){ cin>>x; search2(x); } else if(q==4){ cin>>i>>x; add(i,x); } else if(q==5){ cin>>x; delete_1(x); } else if(q==6) len(); } return 0; }