链表(下)
一、链表的种类
二、常用种类示例
1.单向链表
结点只含一个链域,通常指向后继结点
空表:
非空表:
2.单向加头链表
设计带监督元的链表,是为了更方便的对链表进行操作。
空表:
非空表:
头结点,不存放元素,优势用来存储特殊值。
3.单向加尾链表
是带有表尾监督元的链表。利用监督元可以使查找操作更加方便。
空表:
非空表:
4.单向循环链表
空表:
非空表:
可巡视一周
5.单向加头循环链表
空表:
非空表:
兼有二者优点
6.双向简单链表
结点含有两个链域,一个指向前驱,一个指向后继。可以很方便的进行左右搜索
空表:
非空表:
7.双向加头循环链表
双向加头循环链表是一种具有全部附加特征的完善形式。
空表:
非空表:
三、单向加尾链表的查找
用设置尾监督元的方式完成链表的查找,基本思想与顺序表的带监督元的顺序查找是一样的。
ptr searchB(ptr p,ptr last,int x)
{
last->data = x;//设置监督元
while(p->data!=x)
p=p->next;//没有找到,继续
if(p!=last)return p;//查找成功
return NULL;//查找不成功
}
四、单向加头循环链表的删除
如果频繁的进行查找、插入、删除,不妨采用加头循环链表,表头结点兼做表尾结点。
int deleteBC(ptr h,element_type x)
{
ptr f,p;
f=h,p=h->next;//设置搜索指针初始值
h->head=x;//设置监督元
while(p->data!=x)f=p,p=p->next;
if(p==h) return 0;//删除不成功
f->next = p->next;
free(p);
return 1;//删除成功
}
五、双向链表的插入和删除
结点类型定义为:
typedef struct dnode
{
element_type data;//值域
struct dnode *Llink,*Rlink;//左右链域
}dnode,*dptr;//结构类型名指针类型名
链接关系的特点
1.插在p的左侧:
q->Rlink=p;
q->Llink=q->Llink;
p->Llink=q;
q->Llink->Rlink=q;
2.删除p所指结点
p->Rlink->Llink=p->Llink;
p->Llink->Rlink=p->Rlink;
六、有序链表的构造
一般不能要求用户输入的数据必须是有序,因此需要设计排序的方法。下面的方法为边输入数据,边排序的高效处理方法。插入位置一般分为三种情况:1.小于表头结点,插在表头处;2.大于表尾结点,插在表尾处;3.插在表“中间”p->data<p-data<s->data
。为了提高算法效率,这里就可以使用加头有序循环链表
ptr createlinkBC()
{
ptr head,f,s,p;
element_type x;
head = new snode;
head->data=MAX;//MAX公共监督元
head->next=head;//构造空链表
scanf("%d",&x);
while(x!=End_elm)
{
p = new snode;
p->next=x;
f=head,s=f->next;//设置搜索指针初始值
while(s->data<x) f=s,s=s->next;//有序搜索
f->next=p,p->next=s;//有序插入
scanf("%d",&x);//读入下一个元素
}
return head;
}
七、示例:稀疏多项式求和问题
求P+Q,并且在P表上求和。
如何存储多项式? 链式
如何求和? 有序合并
方法? 加头有序循环链表存储多项式
结点结构和主调程序
typedef struct node
{
int ceof;//系数域
int exp; //指数域
struct node *next;
}snode,*ptr;
void main()
{
……
ha = createlinkdBC();//创建多项式
hb = createlinkdBC();//创建多项式
ha = add_n(ha,hb);
……
}
ptr creatlinkedBC()
{
ptr head,f,s,p;
element_type x;
head = new snode;
head->exp=MAX;
head->next=head;
scanf("%d %d",&coef,&exp);//输入系数和指数
while(exp!=-1)
{
p = new snode;
p->ceof=coef;
p->exp=exp;//创建新结点
f=head,s=f->next;//设置搜索指针初始值
while(s->exp<exp) f=s,s=s->next;//有序搜索
f->next=p,p->next=s;//有序插入
scanf("%d %d",&coef,&exp);//读入下一个元素
}
return head;
}
ptr add_n(ptr ha,ptr hb)
{
ptr p,q,last_p,last_q;
int val;
p = ha->next;
q = hb->next;
last_p = ha;
pre_q = hb;
while(p!=ha&&q!=hb)
{
if(p->exp>q->exp)//第一种情况
{
pre_q->next=q_next;//从hb链表删除q结点
last_p->next=q;//插入ha链表
q->next=p;
last_p=last_p->next;//调整前驱指针位置
q=pre_q->next;
}else if(p->exp<q->exp)//第二种情况
{
last_p=p;
p=p->next;
}else//第三种情况,指数相同的合并
{
val = p->ceof+q->ceof;
if(val!=0)//插入一个,删除一个
{
p->ceof = val;
pre_q->next=q->next;
free(q);
last_p=p;
p=p->next;
q=pre_q->next;
}
else//删除稀疏相加后为0的结点
{
last_p->next=p->next;
pre_q->next=q->next;
free(p);
free(q);
p=last_p->next;
q=pre_q->next;
}
}
}
if(q!=hb)//插入hb中剩余的链表
{
last_p->next=q;
while(q->next!=hb) q=q->next;
q->next=p;
}
free(hb);
return ha;
}