数据结构(三)

单链表的算法设计方法

一、以查找为基础的算法设计

1、按照条件进行节点查找

2、进行插入或者删除操作

例一:找到一个单链表除表头外,其内部的最大值并将它删除(假设单链表内的最大值唯一)

分析:这个例子中我们要做的有两件事,一件事是找到单链表内的最大值,另一件是删除最大值。
那么接下来我们分别去考虑如何实现这两件事情,再将它们合并起来,就能解决问题。

首先是删除,我们知道,要在链表内删除一个数据,需要知道这个数据的前一个链节。

其次是找最大值,我们知道,找最大值,最简单的方法是比较,所以我们需要比较链节本身,也就是我们最后会知道,这个数据所在的链节。

综上所述,我们可以知道我们最后知道的是最大值所在的链结,以及最大值所在链结的前一个链节。

那么实现方法可以是这样:
1、设定两个指针p、q,去遍历整个链表
2、还要设置两指针,(pre、max)在p、q遍历整个链表的时侯去做比较
3、在结束后,让pre=max->next,删除最大值

void delete_max(struct chain*head){
struct chain *p=head,*q=head->next,*pre=head,*max=head->next;
while(q!=NULL){                 //一般来说单链表的尾是指向空的
if(max->data<q->data){
max=q;
pre=p;
}                        //完成比较
p=p->next;
q=q->next;              //p、q去遍历这个链表
}             
pre->next=max->next;  //将最大值从链表里面剔除
free(max);   //释放掉最大值的空间
}

差不多这样就能完成找到最大值,并删除最大值的方法。它的时间复杂度是O(n)。

例二:有一个带头节点的单链表L(至少有一个数据节点),设计一个算法使其元素递增有序排列

分析:当我们要将一个单链表进行排序的时候,我们要做的事有两件,一是比较,二是排序,也就是把数据放到,数据该在的地方。

那么我们依旧将两部分拆开来实现,当然,比较要在排序之前。

比较部分我们这样来想,我们把链表拆成两部分,第一部分是它的头链节,第二部分是剩余链节,我们比较头链节和剩余链节的第一节,如果头链节比剩余链节的第一节小,那么就将剩余链节的第一节放在头链节之后,形成新的两部分,然后再将剩余链节的新的第一节与,新的头链节的那一部分里的所有数据比较,把它插入到正确的位置上就可以了。

void sort(LinkList *&L){
LinkList*p,*pre,*q;
p=L->next;
L->next=NULL;      //将链表拆成两部分
while(p!=NULL){
	q=p->next;
	pre=L;         //从表头开始找
	while(pre->next!=NULL&&pre->next->data<p->data){
		pre=pre->next;                      //查找插入节点的前趋节点
		}
	p->next=pre->next;
	pre->next=p;
	p=q;       //完成插入,直到整个链表排序完成。
  }
}

二、以建表算法为基础的算法设计

1、单链表有尾插法和头插法两种建表算法

2、很多算法是以这两个建表算法为基础进行设计的

例一:将一个链表逆序。

分析:这个实际上,我们可以用排序里的拆开的想法,其实就是头插法和尾插法,我们把链表的头链节拿出来作为一部分,将剩余链节,一节一节的插在这一部分的头部,一直这样重复下去,直到插完,即可将整个链表逆序。

struct chain* turn(struct chain*head){
struct chain*p=head->next,*q=head->next,*pre=head;
head->next=NULL;   //将头链节取下来作为一部分
while(q!=NULL){
q=q->next;
p->next=pre;
pre=p;
p=q;
}   //不断地把剩余部分的第一个链节取下来头插到头链节的那一部分
return pre; //返回新的链表的头指针
}

跟据以上的程序,即可完成一个链表的逆序。

总结

单链表的算法设计里的方法大致可以先划出这两类:

1、链表你要知道是可以拆的,拆了之后再重新组合(有点像原子的重组,组成新的物质,还要知道,不止可以拆成两部分,根据需要可以拆卸成多组)。

2、拆了之后重组有两种方式,一种是头插,一种是尾插,如果你要逆序就头插,顺序就尾插。

3、单链表中,你想处理某个数据时,就一定需要操作他的前置数据,所以要注意记录前置数据。

4、如果你的链表被拆成了好多部分,记得拿指针去记录这几个部分,然后几个部分的交流,需要新的指针去交流,就像是信使一样,以后干脆叫信使指针(自己取地名字,不是专有名词)好了。

总而言之,单链表给我的感觉目前像是织毛衣,链表本身是毛线,指针是毛衣针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值