php程序员玩转算法公开课,韩顺平_PHP程序员玩转算法公开课(第一季)12_双向链表crud操作之_水浒英雄排行_学习笔记_源代码图解_PPT文档整理...

文西马龙:http://blog.csdn.net/wenximalong/链表——双向链表关于按照英雄的排行顺序加入,参考我的这篇博文中的详细图文说明:韩顺平_PHP程序员玩转算法公开课(第一季)03_单链表crud操作之_水浒英雄排行算法_学习笔记_源代码图解_PPT文档整理现在分析添加的情况已经有1号英雄和5号英雄,现在要添加3号英雄此时cur指向了1号英雄,hero指向3号英雄cur指向1号英雄,发现cur的下一个是5号英雄,大于要添加的3号英雄分析图过程(1)让3号英雄指向5号英雄,即把这个①号线搭起来$hero->next=$cur->next; //$cur指向1号英雄,$cur->next指向5号英雄(2)然后再搭pre这根线,让3号英雄的pre指向1号英雄,即把这个②号线搭起来$hero->per=$cur;(3)然后让5号英雄的pre指向3号英雄,即把这个③号线搭起来$cur->next->pre=$hero;//$cur->next指向5号英雄,$cur->next->pre为5号英雄指向1号英雄,即图中⑥号线//此时⑥号线就断掉了,原来的5号英雄的pre是指向1号英雄的,现在指向了3号英雄(4)让1号英雄指向3号英雄,即把这个④号线搭起来$cur->next=$hero;//此时⑤号线就断掉了,原来的$cur->next是指向5号英雄的,现在指向了3号英雄★自己对照图,走一遍,一定要线清楚了doubleLink.php

双向链表完成英雄排行管理


查询英雄

添加英雄

删除英雄

修改英雄

//使用PHP面向对象的方式来完成

class Hero{

public $pre=null; //表示指向前一个节点的引用

public $no;

public $name;

public $nickname;

public $next=null; //表示指向后一个节点的引用

public function __construct($no='',$name='',$nickname=''){

$this->no=$no;

$this->name=$name;

$this->nickname=$nickname;

}

//添加hero,这里我们会构建一个双向链表

//这里使用了静态函数

public static function addHero($head,$hero){

//$head头节点不能动

//$cur为辅助节点,让$cur来穿针引线

$cur=$head;

//isExist 假设英雄不存在

$isExist=FALSE; //这是一个标志位

//首先看看目前的这个链表是不是空的

//当还有英雄的时候,$cur指向的$head节点的next属性必然为null,因为现在只有head节点,还没有添加英雄

//如果是空链表就直接加入

//怎样把空链表和普通链表并和在一起呢?

if($cur->next==null){ //如果是,就说明是空链表,添加第一个英雄

$cur->next=$hero;

//这样就首尾相连了

$hero->pre=$cur;

}else{ //当不是空节点的时候

//如果不是空节点,按照排名来添加

//首先找到添加的位置

while($cur->next!=null){ //只要$cur->next不等于null,就说明没有到队尾

if($cur->next->no > $hero->no){ //说明位置找到了,则说明$hero要加在$cur的后面

break;

}else if($cur->next->no==$hero->no){

$isExist=TRUE;

echo'
不能添加相同的编号';

}

//继续下一个

$cur=$cur->next;

}

//退出该while循环时候,我们只需要把$hero添加到$cur后面即可,(队尾)

//说明还没有这个排名,可以添加,并可以和上面的空链表判断合并

if(!$isExist){ //如果不存在就添加,因为在上面break跳出的时候,就说明找到了,跳出的时候$isExist为假,则!$isExist为真

//添加,有点麻烦

$hero->next=$cur->next;

$hero->pre=$cur;

$cur->next->pre=$hero;

$cur->next=$hero;

}

}

}

//遍历显示双向链表,显示所有英雄的函数

public static function showHero($head){

//上来线做一个辅助指针,穿针引线

$cur=$head->next; //头本来就是空的,这样就输出打印的时候,不输出头了

//$cur=$head; 如果是这样,每次输出的时候会输出:编号= 名字= 外号=

把头也输出了

while($cur->next!=null){ //为空就说明到队尾了

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

//继续下移一步

$cur=$cur->next;

}

//当退出while的时候,$cur就指向了最后的那个节点了

//要是不输出,就会少一个人,少队尾的那个人

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

}

}

//创建一个头节点

$head=new Hero();

//创建一个英雄

$hero=new Hero(1,'宋江','及时雨');

//静态方法的调用

Hero::addHero($head,$hero);

$hero=new Hero(2,'卢俊义','玉麒麟');

Hero::addHero($head,$hero);

$hero=new Hero(6,'林冲','豹子头');

Hero::addHero($head,$hero);

$hero=new Hero(3,'吴用','智多星');

Hero::addHero($head,$hero);

$hero=new Hero(56,'孙二娘','母夜叉');

Hero::addHero($head,$hero);

echo '
英雄排行榜.....';

//显示

Hero::showHero($head);

?> =========改进:不严密的地方,可以和前面的进行合并的添加英雄,把添加时是空链表和不是空链表的情况,合并到一起了现在考虑:要添加的人就在末尾有一个head和1号人物,要添加的是6号人物此时cur指向1号人物,当按照原先的代码执行,既下面这段代码,会有一些小问题的$hero->next=$cur->next;$hero->pre=$cur;$cur->next->pre=$hero;$cur->next=$hero;执行(1)$hero->next=$cur->next; 此时cur指向1号人物,1号人物此时是最后的一个节点,$cur->next就是空了,那么$hero->next=$cur->next; 此时这句话就没有意义了,因为$hero->next本身就是空啊,你再赋给它空,没有意义,干脆这句话此时就不执行了。所以要加一个一个判断条件,即$cur->next不等于空,执行$hero->next=$cur->next; 才有价值if($cur->next!=null){$hero->next=$cur->next;}(2)$hero->pre=$cur; 这句话还是很有价值的,如下图所示,把①号线搭起来了(3)$cur->next->pre=$hero;此时cur指向1号人物,$cur->next就是空了,空的pre就没意义了,所有也要和上面的(1)一样,加判断if($cur->next!=null){$cur->next->pre=$hero;}(4)$cur->next=$hero;这句是有意义的,如下图所示,把②号线搭起来了如果前面的代码修改成了如下的代码:if($cur->next!=null){$hero->next=$cur->next;}$hero->pre=$cur;if($cur->next!=null){$cur->next->pre=$hero;}$cur->next=$hero;就和前面的一个if判断语句不谋而合了即在doubleLink.php中的这段代码if($cur->next==null){ //如果是,就说明是空链表,添加第一个英雄$cur->next=$hero;//这样就首尾相连了$hero->pre=$cur;}else{...都是在说当$cur->next为空的时候,就执行$cur->next=$hero;$hero->pre=$cur;所以可以把前面的if和现在的合并了,修改后的代码为doubleLink2.php

双向链表完成英雄排行管理


查询英雄

添加英雄

删除英雄

修改英雄

//使用PHP面向对象的方式来完成

class Hero{

public $pre=null; //表示指向前一个节点的引用

public $no;

public $name;

public $nickname;

public $next=null; //表示指向后一个节点的引用

public function __construct($no='',$name='',$nickname=''){

$this->no=$no;

$this->name=$name;

$this->nickname=$nickname;

}

//添加hero,这里我们会构建一个双向链表

//这里使用了静态函数

//添加英雄,把添加时是空链表和不是空链表的情况,合并到一起了

public static function addHero($head,$hero){

//$head头节点不能动

//$cur为辅助节点,让$cur来穿针引线

$cur=$head;

//isExist 假设英雄不存在

$isExist=FALSE; //这是一个标志位

//首先看看目前的这个链表是不是空的

//当还有英雄的时候,$cur指向的$head节点的next属性必然为null,因为现在只有head节点,还没有添加英雄

//如果是空链表就直接加入

//怎样把空链表和普通链表并和在一起呢?

while($cur->next!=null){ //只要$cur->next不等于null,就说明没有到队尾

if($cur->next->no > $hero->no){ //说明位置找到了,则说明$hero要加在$cur的后面

break;

}else if($cur->next->no==$hero->no){

$isExist=TRUE;

echo'
不能添加相同的编号';

}

//继续下一个

$cur=$cur->next;

}

//退出该while循环时候,我们只需要把$hero添加到$cur后面即可,(队尾)

//说明还没有这个排名,可以添加,并可以和上面的空链表判断合并

if(!$isExist){ //如果不存在就添加,因为在上面break跳出的时候,就说明找到了,跳出的时候$isExist为假,则!$isExist为真

//添加,有点麻烦

//当你添加的人物就在最后,比如现在只有1号英雄,再添加一个5号英雄,肯定是添加在1号英雄的后面

//这里加上if判断,会更稳健型些

if($cur->next!=null){

$hero->next=$cur->next;

}

$hero->pre=$cur;

if($cur->next!=null){

$cur->next->pre=$hero;

}

$cur->next=$hero;

}

}

//遍历显示双向链表,显示所有英雄的函数

public static function showHero($head){

//上来线做一个辅助指针,穿针引线

$cur=$head->next; //头本来就是空的,这样就输出打印的时候,不输出头了

//$cur=$head; 如果是这样,每次输出的时候会输出:编号= 名字= 外号=

把头也输出了

while($cur->next!=null){ //为空就说明到队尾了

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

//继续下移一步

$cur=$cur->next;

}

//当退出while的时候,$cur就指向了最后的那个节点了

//要是不输出,就会少一个人,少队尾的那个人

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

}

}

//创建一个头节点

$head=new Hero();

//创建一个英雄

$hero=new Hero(1,'宋江','及时雨');

//静态方法的调用

Hero::addHero($head,$hero);

$hero=new Hero(2,'卢俊义','玉麒麟');

Hero::addHero($head,$hero);

$hero=new Hero(6,'林冲','豹子头');

Hero::addHero($head,$hero);

$hero=new Hero(3,'吴用','智多星');

Hero::addHero($head,$hero);

$hero=new Hero(56,'孙二娘','母夜叉');

Hero::addHero($head,$hero);

echo '
英雄排行榜.....';

//显示

Hero::showHero($head);

?> 代码不是一步到位的,优化前进======此时删除英雄就不需要辅助节点了分析图当要删除的节点在最后的时候,还需要判断下此时$cur->next本身就是空了,所有要加判断了$cur->pre->next=$cur->next; //这个就相当于把1号节点的next置空了,这个没错所以要这样:if($cur->next!=null){$cur->next->pre=$cur->pre;}$cur->pre->next=$cur->next;这样执行的话,把上图中的蓝线就去掉了,这样6号英雄就访问不到了,6号英雄出列了,因为我们是从表头开始找的,$cur-next就访问不到6号英雄节点了,6号英雄指向别人是没有用的,★关键★是没有人指向它。注意:要考虑删除第一个和最后一个,(当你的代码考虑不周全的时候)这是最容易出错的,所以要测试doubleLink3.php

双向链表完成英雄排行管理


查询英雄

添加英雄

删除英雄

修改英雄

//使用PHP面向对象的方式来完成

class Hero{

public $pre=null; //表示指向前一个节点的引用

public $no;

public $name;

public $nickname;

public $next=null; //表示指向后一个节点的引用

public function __construct($no='',$name='',$nickname=''){

$this->no=$no;

$this->name=$name;

$this->nickname=$nickname;

}

//添加hero,这里我们会构建一个双向链表

//这里使用了静态函数

//添加英雄,把添加时是空链表和不是空链表的情况,合并到一起了

public static function addHero($head,$hero){

//$head头节点不能动

//$cur为辅助节点,让$cur来穿针引线

$cur=$head;

//isExist 假设英雄不存在

$isExist=FALSE; //这是一个标志位

//首先看看目前的这个链表是不是空的

//当还有英雄的时候,$cur指向的$head节点的next属性必然为null,因为现在只有head节点,还没有添加英雄

//如果是空链表就直接加入

//怎样把空链表和普通链表并和在一起呢?

while($cur->next!=null){ //只要$cur->next不等于null,就说明没有到队尾

if($cur->next->no > $hero->no){ //说明位置找到了,则说明$hero要加在$cur的后面

break;

}else if($cur->next->no==$hero->no){

$isExist=TRUE;

echo'
不能添加相同的编号';

}

//继续下一个

$cur=$cur->next;

}

//退出该while循环时候,我们只需要把$hero添加到$cur后面即可,(队尾)

//说明还没有这个排名,可以添加,并可以和上面的空链表判断合并

if(!$isExist){ //如果不存在就添加,因为在上面break跳出的时候,就说明找到了,跳出的时候$isExist为假,则!$isExist为真

//添加,有点麻烦

//当你添加的人物就在最后,比如现在只有1号英雄,再添加一个5号英雄,肯定是添加在1号英雄的后面

//这里加上if判断,会更稳健型些

if($cur->next!=null){

$hero->next=$cur->next;

}

$hero->pre=$cur;

if($cur->next!=null){

$cur->next->pre=$hero;

}

$cur->next=$hero;

}

}

//删除某位英雄,现在不需要辅助节点了

public static function delHero($head,$herono){

//我们不使用辅助节点了

//先找到$head

//$head不能动

//直接让$cur指向下一个,$head->next就是具体的英雄了,当然还要先判断,$cur->next是不是空,要是空,就是光有head了,也没有要删除的了

$cur=$head->next;

$isFind=flase; //先搞个标志位

while($cur!=null){

if($cur->no==$herono){

//找到了,就置为true,并跳出

$isFind=true;

break;

}

//如果上面的if没有找到,就不停的向下走

$cur=$cur->next;

}

if($isFind){

//当$isFind为真的时候,就说明找到了

//执行删除

//自我删除

//这里考虑了要删除的英雄在末尾的时候情况

if($cur->next!=null){

$cur->next->pre=$cur->pre;

}

$cur->pre->next=$cur->next;

echo '
要删除的英雄编号是'.$cur->no;

}else{

echo'
要删除的英雄没有';

}

}

//遍历显示双向链表,显示所有英雄的函数

public static function showHero($head){

//上来线做一个辅助指针,穿针引线

$cur=$head->next; //头本来就是空的,这样就输出打印的时候,不输出头了

//$cur=$head; 如果是这样,每次输出的时候会输出:编号= 名字= 外号=

把头也输出了

while($cur->next!=null){ //为空就说明到队尾了

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

//继续下移一步

$cur=$cur->next;

}

//当退出while的时候,$cur就指向了最后的那个节点了

//要是不输出,就会少一个人,少队尾的那个人

echo'
编号='.$cur->no.'名字='.$cur->name.'外号='.$cur->nickname;

}

}

//创建一个头节点

$head=new Hero();

//创建一个英雄

$hero=new Hero(1,'宋江','及时雨');

//静态方法的调用

Hero::addHero($head,$hero);

$hero=new Hero(2,'卢俊义','玉麒麟');

Hero::addHero($head,$hero);

$hero=new Hero(6,'林冲','豹子头');

Hero::addHero($head,$hero);

$hero=new Hero(3,'吴用','智多星');

Hero::addHero($head,$hero);

$hero=new Hero(56,'孙二娘','母夜叉');

Hero::addHero($head,$hero);

echo '
英雄排行榜.....';

//显示

Hero::showHero($head);

echo'
';

echo '
删除后的英雄排行榜.....';

Hero::delHero($head,3);

Hero::showHero($head);

echo'
';

echo'
下面测试删除最前面的和最后面的英雄
';

echo '
删除后的英雄排行榜.....';

Hero::delHero($head,1);

Hero::showHero($head);

echo'
';

echo '
删除后的英雄排行榜.....';

Hero::delHero($head,56);

Hero::showHero($head);

?> 双向链表的好处:双向链表可以完成自我删除,效率高一些,而且学明白双向链表后,为你将来,学习二叉树,霍夫曼树等等,打下了良好的基础通过学习,一定要建立编程的思想,思考复杂的现象,在内存中是怎么倒腾的。韩顺平_PHP程序员玩转算法公开课_学习笔记_源代码图解_PPT文档整理_目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值