前几天刚把链表的练习做完,来记录一下成果,因为自己大部分都是自学,特明白小白的痛苦,那就是思想明白,但是代码写不出来,所以给出一个适合小白的入手代码,全部都是c++代码。
①创建一个链表
输入n个整数按输入,顺序(逆序)建表
#include<iostream>
using namespace std;
struct node
{
int data;
struct node *next;
};
/*****顺序建表******/
node *cListR(node *head,int n)
{
node *tail=head,*p;
for(int i=0;i<n;i++)
{
p=new struct node();
p->next=NULL;
cin>>p->data;
tail->next=p;
tail=p;
}
return head;
}
/*****逆序建表*****/
node *cListL(node *head,int n)
{
node *tail=head,*p;
for(int i=0;i<n;i++)
{
p=new struct node();
p->next=NULL;
cin>>p->data;
p->next=head->next;
head->next=p;
}
return head;
}
int main()
{
int n;
cin>>n;
node *head,*p;
head=new struct node(); //为头结点开辟空间
head->next=NULL; //头结点数据域不起作用,只是用指针域
p=cListR(head,n); //这里调用的顺序建表函数
for(p=p->next;p!=NULL;p=p->next)
cout<<p->data<<' ';
return 0;
}
②插入元素单链
这个其实在上面的建表过程中已经使用过了,下面在详细的说一下
a c 中间插入b
b->next=a->next;
a->next=b;
第一句是先让b指向c,第二句让a指向b,这样b就插入到了中间。
这两句的顺序也是不能反的,因为如果反过来的的话,先是a->next=b;然后再b->next=a->next;
那就成了b指向b了,显然这个表就被破坏了
③删除元素单链
删除元素过程也很简单,与插入元素的原理基本相同,也是修改指针域
a b c 删除b结点
a->next=b->next; //使得a直接指向了c
这样我们在从前往后遍历链表的时候,遍历到a,下一个直接就是c,这样b就相当于删除了
④链表归并(非递减排列)
已知单链表La,Lb非递减排列,归并后Lc也为非递减排列
例如:
La:1 3 5 6 8 9
Lb:2 4 6 9 10
Lc:1 2 3 4 5 6 6 8 9 9 10
node *MergeList(node *La,node *Lb,node *Lc)
{
node *pa,*pb,*pc;
pa=La->next;
pb=Lb->next;
Lc=Lb; //将第二个链表的头结点,当做归并后的头结点
pc=Lc;
while(pa&&pb) //当一个链表遍历结束时,停止循环
{
if(pa->data<=pb->data)
{
pc->next=pa; //pc不断在两个链表之间跳跃,改变相应结点的指针指向,
//使之最终变成一条链
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next = pa ? pa : pb; //判断循环跳出是因为那个链表结束,让pc指向没结束的那个
//条件运算符:这里判断的是pa
//如果pa为NULL,那么返回pb,否则返回pa
return Lc;
}
以上代码就是归并的函数代码
单链表与双链表在插入和删除有区别
⑤双链表插入
涉及到了前插和后插,例如
在p前面插入s结点
struct node
{
int data;
struct node *prior; //前指针
struct node *next; //后指针
};
s->prior = p->prior;
p->prior->next = s;
s->next = p;
p->prior = s;
大家可以想一下在p后面插入s结点的代码
⑥双链表的删除
删除p结点
p->prior->next = p->next;
p->next->prior = p->prior;