传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
聊天篇:
数学对我们编程来说,重不重要?
看你站在什么样的层次来说. 如果你应用程序开发,对数学要求不高
但是,如果你开发系统软件,比如(搜索/识别软件[图像,语言识别]/操作系统...)对数学高
建模.大量数学模型.
老师啊啊。我是学C++的。麻烦,谈哈对QT和MFC的看法嘛。前景什么的,
记住 : 打好基础,大有可为!
初中毕业能去传智学习吗?
学习It, 不管是java ,php ,c#,对学历要求不高.
学历不是问题,能力是问题!
老师听完您的视频可以去找工作吗?
如果你的自学能力比较强,看完视频可以找份 4000 ,如果你理解的层次比较到位 6000 + 你的表达+英语水平+学历(大专)-> 6500
8000以上,学习项目[自己去研究一些开源的项目 ec /dedecms/ phpcms ...]
学习的怎样!!!
有必要学php又学java吗
我个人认为,学习好一门,然后再学习其它.
做架构师,建议多学习是没有害处!
求学者 (19:54:16)
我学历低,我英语差,可是看了韩爷就找到工作!很好!
我是大四毕业生,已经做完你的j2ee校内网了,快要找工作了,面试主要有什么技巧和方法呢?韩爷!
最好你可以把你项目上线->公网
面试前,看看传智播客java笔试大全->笔试题oK!
面试时,不要怕,敢于和面试官交流!===>自信
这个链表要怎么练习才会比较熟练!~!->多练
卖油翁的故事!-> 巧是熟练出来 聪明人(举一反三) 笨鸟(举三反一)
编程
思想(自己知道怎么做)—(多练习)--->代码(熟练的掌握基本语法)
老师java程序员以后的发展方向都有哪些?
- web程序员->网站应用
- 手机开发,安卓开发.
听的懂 写不了代码啊
思想---(艰苦练习)--->代码
约瑟夫问题?
学以致用!
学习的套路
用一个小案例,来学习知识快速入门-->对细节研究--->把一个知识点运用到一个综合案例--->知识点运用到项目中.
数据库(mysql/oralce)-->思考如果让你去开发一个团购网(数据库的表应该怎么设计.)->看开源项目 (PHP有很多开源项目 discuz ec dedecms phpcms ) 这样方式成长最快!
我是大四数学系的学生,自学的PHP,请问韩老师,我毕业到哪类公司实习对自己提高最快呀? =>建议可以到做搜索引擎这方面的公司 , 做系统软件开发(数据库/操作开发/网络安全/识别软件)
数学+计算机编程
老师什么时候讲一下CMS吧,对大项目很吃力呀!
我们传智播客 dedecms 七天 / phpcms / cmstop
老师android开发容易吗?要怎样入门和深入啊?
可以看看黎活明老师andriod视频
大体讲讲老师你学习编程的经历。。。。,没事老师多开几次交流会吧,,数据库的设计太重要了,深有体会?
大学我们 c/c++ =>五子棋 学习编译原理 PL0编译器,可以完成 if else 和+/-/*/操作 =>基础很好.
毕业时候.英语学习机()=> 这段时间成长最快 【独立解决问题能力】
用友开发(vb=>erp)=>点击科技(服务器群集 c/c++/linux/solaris)=>新浪(uc/电子邮件)=>培训06到现在[真正要做什么?] php java
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
u 什么是算法?
程序=数据结构+算法
说:我们使用数据结构(int->数组、链表、队列、二叉树,散列...)+ 一些逻辑(if, for , while...) =完成某个任务
思考: 为什么有些网站可以支持千万以上人来访问? 点击科技和新浪工作.(产品竟开协同软件| 新浪邮件) ->问题?我在公司内部测试一切ok! 登录时候
解决方法 :首任sina CTO->三天优化. 结论: 程序是有灵魂,就是算法
百度/google/腾讯/淘宝=>如果不想当一个coder,你一定看算法.[设计模式]/
u 算法有什么用,在什么地方用?
提出几个实际的问题?
<?php
$str="abc,ytkhello,abc,北京";
//echo str_replace('abc','传智播客',$str);
?>
你能不能做一个字符串这样的一个数据结构.可以做成:
试写出用单链表表示的字符串类及字符串结点类的定义,并依次实现它的构造函数、以及计算串长度、串赋值、判断两串相等、求子串、两串连接、求子串在串中位置等7个成员函数。要求每个字符串结点中只存放一个字符。
比如: 你做一个五子棋游戏:
这里,如何判断赢,算法, 悔棋算法,接着上局继续玩算法.
u 再提出一个问题: 约瑟夫问题(丢手帕问题)[最常见一个笔试题.]
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
直接走代码
今天我们就要使用 环形链表把这个问题解决.
总而言之,算法是很重要,是程序的灵魂.
u 链表-最灵活的数据结构
什么是链表: 链表是一个有序的列表,但是他在内存中时分散存储的. 使用链表可以解决类似约瑟夫问题, 排序, 索引 ,广义表...
u 链表的快速入门案例-水浒英雄排行榜管理
我使用PHP语言来实现, 如果是c#/c/c++/java 思路是完全一样.
现在我们看看链表是怎样的一种数据结构呢?->内存图:
我们不让有相同排名的英雄入链表.
最后的代码 singleLink.php
<html>
<head>
<meta http-equiv="content-type" content='text/html;charset=utf-8'/>
</head>
<h1>单向链表完成英雄排行管理</h1>
<hr/>
<a href='#'>查询英雄</a>|
<a href='#'>添加英雄</a>|
<a href='#'>删除英雄</a>|
<a href='#'>修改英雄</a>
<?php
//首先需要基础知识 。 知道什么是 变量, 有一些面向对象编程基础,
//知道 if for while 的语句.
//定义英雄类
class Hero{
//属性
public $no;//排名
public $name;//真实名字
public $nickname;//外号
public $next=null;//$next是一个引用.指向另外一个Hero的对象实例.
//构造函数
public function __construct($no='',$name='',$nickname=''){
//赋值
$this->no=$no;
$this->name=$name;
$this->nickname=$nickname;
}
}
//因为有些同学,对PHP语法有点不熟.我演示一下
//创建一个head头,该head 只是一个头,不放入数据
$head=new Hero();
//创建一个英雄
/* $hero=new Hero(1,'宋江','及时雨');
//连接,使用的是比较二的方法,马上改进
$head->next=$hero;
$hero2=new Hero(2,'卢俊义','玉麒麟');
$hero->next=$hero2;*/
//写一个函数,专门用于添加英雄.
function addHero($head,$hero){
//1.直接在链表最后加.
//找到链表最后,不能动$head;
$cur=$head;
/*while($cur->next!=null){
$cur=$cur->next;
}
//当退出 while循环时,$cur就是链表最后.
$cur->next=$hero;*/
//2.按照英雄的排行加入.(这里我希望能够保证链表的顺序)
//思路:
$flag=false;//表示没有重复的编号
while($cur->next!=null){
if($cur->next->no>$hero->no){
//找到位置
break;
}else if($cur->next->no==$hero->no){
$flag=true;
echo '<br/>不能抢位置,'.$hero->no.'位置已经有人了';
}
//继续
$cur=$cur->next;
}
// 当退出while时候,位置找到.
//加入
//让hero加入
if($flag==false){
$hero->next=$cur->next;
$cur->next=$hero;
}
}
//单链表的遍历怎么做,是从head开始遍历的,
//$head头的值不能变,变化后就不能遍历我们的单链表
function showHeros($head){
//遍历[必须要知道什么时候,到了链表的最后.]
//这里为了不去改变 $head的指向,我们可以使用一个临时的遍历
$cur=$head;
while($cur->next!=null){
echo '<br/>英雄的编号是'.$cur->next->no.' 名字='.$cur->next->name.' 外号='.$cur->next->nickname;
//让$cur移动
$cur=$cur->next;
}
}
//从链表中删除某个英雄
function delHero($head,$herono){
//找到这个英雄在哪里
$cur=$head;// 让$cur指向$head;
$flag=false;//假设没有找到
while($cur->next!=null){
if($cur->next->no==$herono){
$flag=true;
// 找到 $cur的下一个节点就是应该被删除的节点.
break;
}
$cur=$cur->next;
}
if($flag){
//删除
$cur->next=$cur->next->next;
}else{
echo '<br/>没有你要删除的英雄的编号'.$herono;
}
}
//修改英雄
function updateHero($head,$hero){
//还是还找到这个英雄
$cur=$head;//$cur就是跑龙套.
while($cur->next!=null){
if($cur->next->no==$hero->no){
break;
}
//继续下走.
$cur=$cur->next;
}
//当退出while 后,如果$cur->next==null 说明
if($cur->next==null){
echo '<br/>你要修改的'.$hero->no.'不存在';
}else{
//编号不能改
$cur->next->name=$hero->name;
$cur->next->nickname=$hero->nickname;
}
}
//添加
$hero=new Hero(1,'宋江','及时雨');
addHero($head,$hero);
$hero=new Hero(2,'卢俊义','玉麒麟');
addHero($head,$hero);
$hero=new Hero(7,'秦明','霹雳火');
addHero($head,$hero);
$hero=new Hero(6,'林冲','豹子头');
addHero($head,$hero);
$hero=new Hero(3,'吴用','智多星');
addHero($head,$hero);
$hero=new Hero(3,'吴用2','智多星2');
addHero($head,$hero);
echo '<br/>************当前的英雄排行情况是*******';
showHeros($head);
echo '<br/>************删除后额英雄排行情况是*******';
//delHero($head,1);
delHero($head,21);
showHeros($head);
echo '<br/>************修改后额英雄排行情况是*******';
$hero=new Hero(1,'韩顺平','左青龙,右白虎');
updateHero($head,$hero);
showHeros($head);
?>
</html>
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
关键是运行,明天我们讲的知识就是用 环形链表解决丢手帕问题.,加深认识.
现在我们读单链表有了基本的了解.现在在学习一个环形链表
现在我们来完成约瑟夫问题的解决方案!
1. Josephu 问题
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。并求出最后出列的人是哪个?
提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束
思路:
(1) 构建一个环形链表,链表上的每个节点,表示一个小朋友 (PHP语句实现)/c/c++/C#/java
请发送到我的邮箱 hanshunping@tsinghua.org.cn
(2) 写一个函数来显示圈圈的所有小孩子.
关键是你们脑海中,有一个内存分布和运行的大致图.
(3) 写了一个函数来完成这个游戏.
(4) 最后的代码:
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8'/>
</head>
<h1>约瑟夫问题解决</h1>
<?php
//1(1) 构建一个环形链表,链表上的每个节点,表示一个小朋友
//小孩类
class Child{
public $no;
public $next=null;
//构造函数
public function __construct($no){
$this->no=$no;
}
}
//定义一个指向第一个小朋友的引用
$first=null;
$n=4000;//$n表示有几个小朋友
//写一个函数来创建一个四个小朋友的环形链表
//一会,我们深入的分析&$first时间57:22如果没有&那么就指向堆区的对象,如果有&就保存的是指向对象栈区的变量的地址,是通过栈区的变量去修改的,这里方法里面的变量无法直接联系对象,而是通过指向对象的变量这个代理来修改数据,或者
//这样理解,两个指向对象的变量是一个克隆关系,同步变化,这就是地址传递。这里要用这个是因为firt是在不断变化。不断变化地指向不同的小孩。
/**
addChild函数的作用是: 把$n个小孩构建成一个环形链表,$first变量就指向该
环形链表的第一个小孩子
*/
function addChild(&$first,$n){
//死去活来
//1. 头结点不能动 $first不能动.
$cur=null;
for($i=0;$i<$n;$i++){
$child=new Child($i+1);
//怎么构成一个环形链表.
if($i==0){
$first=$child;
$first->next=$child;
$cur=$first;
}else{
$cur->next=$child;
$child->next=$first;
$cur=$cur->next;
}
}
}
//遍历所有的小孩,显示,必须把头$first 给函数.
function showChild($first){
//遍历 $cur变量是帮助我们遍历环形链表,所以不能动.
$cur=$first;
while($cur->next!=$first){
//显示
echo '<br/>小孩的编号是'.$cur->no;
$cur=$cur->next;
}
//当退出while循环时,已经到了环形链表的最后,所以还要处理一下最后这个
//小孩节点
//显示
echo '<br/>小孩的编号是'.$cur->no;
}
$m=31;
$k=20;
//问题简化,从第一个小孩开始数,数2.看看出圈的顺序
function countChild($first,$m,$k){
//思考:因为我们找到一个小孩,就要把他从环形链表删除,
// 为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩
//在 $first前面.
$tail=$first;
while($tail->next!=$first){
$tail=$tail->next;
}
//考虑是从第几个人开始数数
for($i=0;$i<$k-1;$i++){
$tail=$tail->next;
$first=$first->next;
}
//当退出while时,我们的$tail就指向了最后这个小孩
//让$first和$tail向后移动.
//移动一次,相当于数2下.
//移动2次,相当于数了3下,因为自己数的时候是不需要动的.
while($tail!=$first){ //当$tail==$first则说明只有最后一个人了.
for($i=0;$i<$m-1;$i++){
$tail=$tail->next;
$first=$first->next;
}
echo '<br/>出圈额人的编号是'.$first->no;
//把$first指向的节点小孩删除环形链表
$first=$first->next;
$tail->next=$first;
}
echo '<br/>最后留在圈圈的人的编号是'.$tail->no;
}
addChild($first,$n);
showChild($first);//死悄悄
//真正的来玩游戏.
countChild($first,$m,$k);
?>
</html>
我给你一个字符串
“4*8-(9-8)/2+4*67” =>必须学会使用栈来搞定.
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
u 堆栈-最神奇的数据结构
什么是堆栈:
堆栈使用的地方:
1.子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
2.处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
3.表达式的转换与求值。//综合的计算器
4.二叉树的遍历。//前序遍历,后序遍历,中序遍历
5.图形的深度优先(depth一first)搜索法。//搜索算法
u 我们来一个快速入门案例,来初步的了解栈的使用
//一般说,现在的编程语句都提供栈的一些基本操作,比如:入栈, 出栈都有,我们今天自己来实现 入栈, 出栈操作.
在php 的数组就提供了 入栈 array_push , 出栈 array_pop
<?php
$stack = array("orange", "banana");
array_push($stack, "apple", "葡萄");
echo "<pre>";
print_r($stack);
echo "</pre>";
//出栈[把栈顶的数据,取出来.]
$val=array_pop($stack);
echo '<br/>栈顶='.$val;
$val=array_pop($stack);
echo '<br/>栈顶='.$val;
echo "<pre>";
print_r($stack);
echo "</pre>";
?>
现在,我们自己使用数组来实现,出栈和入栈的操作.
最后的代码:
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8'/>
</head>
<h1>使用数组来模拟栈的各种操作</h1>
<?php
class MyStack{
private $top=-1;//默认是-1,表示该栈是空的
private $maxSize=5;//$maxSize表示栈最大容量
private $stack=array();//
//入栈的操作
public function push($val){
//先判断栈是否已经满了
if($this->top==$this->maxSize-1){
echo '<br/>栈满,不能添加';
return;
}
$this->top++;
$this->stack[$this->top]=$val;
}
//出栈的操作,就是把栈顶的值取出
public function pop(){
//判断是否栈空
if($this->top==-1){
echo '<br/>栈空';
return;
}
//把栈顶的值,取出
$topVal=$this->stack[$this->top];
$this->top--;
return $topVal;
}
//显示栈的所有数据的方法.
public function showStack(){
if($this->top==-1){
echo '<br/>栈空';
return;
}
echo '<br/>当前栈的情况是....';
for($i=$this->top;$i>-1;$i--){
echo '<br/> stack['.$i.']='.$this->stack[$i];
}
}
}
$mystack=new MyStack;
$mystack->push('西瓜');
$mystack->push('香蕉');
$mystack->push('橘子');
$mystack->push('柚子');
$mystack->push('柚子x');
$mystack->showStack();
$val=$mystack->pop();
echo '<br/>pop出栈了一个数据'.$val;
$mystack->showStack();
$val=$mystack->pop();
echo '<br/>pop出栈了一个数据'.$val;
$mystack->showStack();
$val=$mystack->pop();
echo '<br/>pop出栈了一个数据'.$val;
$mystack->showStack();
$val=$mystack->pop();
echo '<br/>pop出栈了一个数据'.$val;
$mystack->showStack();
?>
</html>
总结:首先使用环形链表,解决约瑟夫问题,然后我们分析了 在PHP 对象传递的原理,后面我们自己是使用数据模拟一个站的操做 =>目标使用我们自己的栈,我完成 一个综合的表达式的计算 .
简单回顾: 昨天讲了 使用环形链表来解决 约瑟夫问题, 然后我们还讲解了 使用数组来模拟一个栈的操作(pop, push ,打印这个栈数据)
今天的课程.
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
使用堆栈开发一个 高级的计算器
3+2*6-2 你把结果给我计算出来!
问一个问题? 有没有一个函数,可以把个字符串当做一个运算字符来执行?
说: 即使你使用 一个函数就可以把这个算出,他的底层一定是堆栈来实现!
步骤
- 界面搞定.
- 思路->画图说明
- 现在处理一下多位数的运算.
- 处理连续是减号的运算符.
思考: 请大家思考如何给我们的运算字符,带上 ()
6*8-(90-78)+60-45
6*{8-[(90-78)+60]-45}
6*(8-90)
思考=>思路 我们给( [ { 都设置运算的优先级 来处理不同的运算
有同学作出,然后发送到 hanshunping@tsinghua.org.cn java/c/c++/c#/PHP
u 综合计算器的最后代码
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8'/>
</head>
<h1>高级计算器</h1>
<?php
//$exp=$_GET['exp'];
//$exp='300+20*6-20';
$exp='71*2-50*3-3-67*6+80'; //14-15-3=-4
//定义一个数栈和一个符号栈
$numsStack=new MyStack();
$operStack=new MyStack();
$keepNum='';//专门用于拼接多位数的字符串
$index=0;//$index就是一个扫描的标记
while(true){
//依次取出字符
$ch=substr($exp,$index,1);
//判断$ch是不是一个运算符号.
if($operStack->isOper($ch)==true){
//是运算符
/**
3.如果发现是运算符
3.1 如果符号栈为空,就直接入符号栈
3.2. 如何符号栈,不为空,就判断
如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈.然后把当前符号入栈
3.3 如何符号栈,不为空,就判断
如果当前运算符的优先级大于符号栈顶的这个运算符的优先级,就入栈.
*/
if($operStack->isEmpty()){
$operStack->push($ch);
}else{
//需要一个函数,来获取运算符的优先级. * 和 / 为 1 + -为0
// $chPRI=$operStack->PRI($ch);
// $stackPRI=$operStack->PRI($operStack->getTop());
while(!$operStack->isEmpty() && $operStack->PRI($ch)<=$operStack->PRI($operStack->getTop())){
//从数栈依次出栈两个数.
$num1=$numsStack->pop();
$num2=$numsStack->pop();
//再从符号栈取出一个运算符
$oper=$operStack->pop();
//这里还需要一个计算的函数
$res=$operStack->getResult($num1,$num2,$oper);
//把$res入数栈<font size="" color=""></font>
$numsStack->push($res);
}
//把当前这个符号再入符号栈.//???????问题,一会在解决
$operStack->push($ch);
//需要一个函数,来获取运算符的优先级. * 和 / 为 1 + -为0
/* $chPRI=$operStack->PRI($ch);
$stackPRI=$operStack->PRI($operStack->getTop());
if($chPRI<=$stackPRI){
//从数栈依次出栈两个数.
$num1=$numsStack->pop();
$num2=$numsStack->pop();
//再从符号栈取出一个运算符
$oper=$operStack->pop();
//这里还需要一个计算的函数
$res=$operStack->getResult($num1,$num2,$oper);
//把$res入数栈<font size="" color=""></font>
$numsStack->push($res);
//把当前这个符号再入符号栈.//???????问题,一会在解决
$operStack->push($ch);
}else{
$operStack->push($ch);
}*/
}
}else{
$keepNum.=$ch;
//先判断是否已经到字符串最后.如果已经到最后,就直接入栈.
if($index==strlen($exp)-1){
$numsStack->push($keepNum);
}else{
//要判断一下$ch字符的下一个字符是数字还是符号.
if($operStack->isOper(substr($exp,$index+1,1))){
$numsStack->push($keepNum);
$keepNum='';
}
}
}
$index++;//让$index指向下一个字符.
//判断是否已经扫描完毕
if($index==strlen($exp)){
break;
}
}
/*
4. 当扫描完毕后,就依次弹出数栈和符号栈的数据,并计算,最总留在数栈的值,就是运算结果,只有符号栈不空就一直计算
*/
while(!$operStack->isEmpty()){
$num1=$numsStack->pop();
$num2=$numsStack->pop();
$oper=$operStack->pop();
$res=$operStack->getResult($num1,$num2,$oper);
$numsStack->push($res);
}
//当退出while后,在数栈一定有一个数,这个数就是最后结果
echo $exp.'='.$numsStack->getTop();
//这是我们昨天写的一个栈.
class MyStack{
private $top=-1;//默认是-1,表示该栈是空的
private $maxSize=5;//$maxSize表示栈最大容量
private $stack=array();//
//计算函数
public function getResult($num1,$num2,$oper){
$res=0;
switch($oper){
case '+':
$res=$num1+$num2;
break;
case '-':
$res=$num2-$num1;
break;
case '*':
$res=$num1*$num2;
break;
case '/':
$res=$num2/$num1;
break;
}
return $res;
}
//返回栈顶的字符,只是取出,但是不出栈
public function getTop(){
return $this->stack[$this->top];
}
//判断优先级的函数
public function PRI($ch){
if($ch=='*'||$ch=='/'){
return 1;
}else if($ch=='+'||$ch=='-'){
return 0;
}
}
//判断栈是否为空
public function isEmpty(){
if($this->top==-1){
return TRUE;
}else{
return FALSE;
}
}
//增加一个函数[提示,在我们开发中,根据需要可以灵活的增加你需要的函数]
//判断是不是一个运算符
public function isOper($ch){
if($ch=='-'||$ch=='+'||$ch=='*'||$ch=='/'){
return TRUE;
}else{
return FALSE;
}
}
//入栈的操作
public function push($val){
//先判断栈是否已经满了
if($this->top==$this->maxSize-1){
echo '<br/>栈满,不能添加';
return;
}
$this->top++;
$this->stack[$this->top]=$val;
}
//出栈的操作,就是把栈顶的值取出
public function pop(){
//判断是否栈空
if($this->top==-1){
echo '<br/>栈空';
return;
}
//把栈顶的值,取出
$topVal=$this->stack[$this->top];
$this->top--;
return $topVal;
}
//显示栈的所有数据的方法.
public function showStack(){
if($this->top==-1){
echo '<br/>栈空';
return;
}
echo '<br/>当前栈的情况是....';
for($i=$this->top;$i>-1;$i--){
echo '<br/> stack['.$i.']='.$this->stack[$i];
}
}
}
?>
</html>
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn
u 这里我们讲解了双向链表,完成了一个水浒英雄排行榜.
双向链表可以完成自我删除,效率相对高,而且你明白这双向链表后,为你将来学习 二叉树打下良好基础.
最后的代码:
<html>
<head>
<meta http-equiv="content-type" content='text/html;charset=utf-8'/>
</head>
<h1>双向链表完成英雄排行管理</h1>
<hr/>
<a href='#'>查询英雄</a>|
<a href='#'>添加英雄</a>|
<a href='#'>删除英雄</a>|
<a href='#'>修改英雄</a>
<?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){
$cur=$head;
//isExist假设不存在
$isExist=false;
//如果是空链表就直接加入.
//给找到一个合适的位置.
while($cur->next!=null){
if($cur->next->no>$hero->no){
//找到位置
break;
}else if($cur->next->no==$hero->no){
$isExist=TRUE;
echo '<br/>不能抢位置. '.$hero->no.'有人了';
}
//继续判断
$cur=$cur->next;
}
//说明还没有这个排名,可以添加,并可以和上面的合并
if(!$isExist){
//比如你添加的人就在最后.
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){
//我们不使用辅助引用
$cur=$head->next;
$isFind=false;
while($cur!=null){
if($cur->no==$herono){
//找到.
$isFind=true;
break;
}
//下找.
$cur=$cur->next;
}
if($isFind){
//删除
if($cur->next!=null){
$cur->next->pre=$cur->pre;
}
$cur->pre->next=$cur->next;
echo '<br/>要删除的英雄编号是'.$cur->no;
}else{
echo '<br/>要删除的英雄没有';
}
}
//显示所有英雄
public static function showHero($head){
$cur=$head;
while($cur->next!=null){
echo '<br/>排名: '.$cur->next->no.' 名字:'.$cur->next->name.' 外号:'.$cur->next->nickname;
$cur=$cur->next;
}
}
}
//创建一个头节点
$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(4,'公孙胜','入云龙');
Hero::addHero($head,$hero);
echo '<br/> 英雄排行';
Hero::showHero($head);
echo '<br/> 删除后的英雄排行';
Hero::delHero($head,1);
Hero::delHero($head,6);
Hero::showHero($head);
?>
</html>
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn