php实现单,双向链表,环形链表解决约瑟夫问题

传智播客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程序员以后的发展方向都有哪些?

  1. web程序员->网站应用
  2. 手机开发,安卓开发.

听的懂 写不了代码啊

思想---(艰苦练习)--->代码

约瑟夫问题?

学以致用!

学习的套路

用一个小案例,来学习知识快速入门-->对细节研究--->把一个知识点运用到一个综合案例--->知识点运用到项目中.

数据库(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

请发送到我的邮箱 [email protected]

(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  你把结果给我计算出来!

问一个问题? 有没有一个函数,可以把个字符串当做一个运算字符来执行?

说: 即使你使用 一个函数就可以把这个算出,他的底层一定是堆栈来实现!

步骤

  1. 界面搞定.
  2. 思路->画图说明
  3. 现在处理一下多位数的运算.
  4. 处理连续是减号的运算符.

思考: 请大家思考如何给我们的运算字符,带上 ()

6*8-(90-78)+60-45

6*{8-[(90-78)+60]-45}

6*(8-90)

思考=>思路 我们给( [ { 都设置运算的优先级 来处理不同的运算

有同学作出,然后发送到 [email protected]  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

时间: 2024-10-18 02:37:12

php实现单,双向链表,环形链表解决约瑟夫问题的相关文章

java 环形链表实现约瑟夫(Joseph)问题

约瑟夫问题又名丢手绢问题.相传著名犹太历史学家 Josephus 利用其规则躲过了一场自杀游戏,而后投降了罗马. 问题: 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.* 从编号为k的人开始报数,数到m的那个人出列:* 他的下一个人又从1开始报数,数到m的那个人又出列:* 依此规律重复下去,直到圆桌周围的人全部出列. 用节点来模拟游戏中的人,用链表来表示游戏中的人按一定的顺序排列.每一个节点给一个编号,从编号为k的节点开始计数,计到m的节点从链表中退出.之后m的下一个节点从新

环形链表与约瑟夫环问题

思路: 代码: public class Josepfu { public static void main(String[] args) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(125);// 加入5个小孩节点 circleSingleLinkedList.showBo

使用java的循环单向链表解决约瑟夫问题

什么是约瑟夫问题 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而Josephus 和他的朋友并不想遵从.首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人.接着,再越过k-1个人,并杀掉第k个人.这

数据结构和算法--3链表(单向链表、双向链表、环形单向链表和约瑟夫问题)

链表 链表是以节点的方式来存储 每个节点包含data域和next域,指向下一个节点 链表的各个节点不一定是连续存储 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定 单向列表 最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能. 单链表分为两种:有头链表和无头链表. 有头节点的增删改查 定义一个单链表的类: //定义一个SingleLinkedList,单链表,管理HeroNode class SingleLinkedList{ //初始

双向链表和环形链表(约瑟夫问题)

双向链表 package linkedlist; public class DooubleLinkedListDemo { public static void main(String[] args) { HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨"); HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟"); HeroNode2 hero3 =

Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)

1.Josephu(约瑟夫.约瑟夫环)问题: 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列. 提示: 用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法

C# 数据结构 - 单链表 双链表 环形链表

链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了.(顺序表可以弥补这缺点,但插入和删除就非常耗性能) 单链表 单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针).最后一个节点的Next为null来标识链表的尾. 如下图 代码实现 1 /* ----

(java描述)关于链表的代码-----单双、循环链表、约瑟夫环、多项式相加

将链表头尾倒置 将几个链表合并成一个新的链表,将链表中重复的节点去掉,并按大小排序 双向循环链表 单向循环链表(约瑟夫循环) 多项式相加 程序源代码 单链表.单向循环链表结点类 package javab; public class Node { int data; Node next; public Node(int data){ this.data=data; } } 第一题代码: package javab; import java.util.Scanner; public class I

实现约瑟夫环形链表

题目 41个人排成一个圆圈,由第1个人 开始报数,每报数到第3人,该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.约瑟夫与朋友在第16与第31个位置,于是活了下来.请用单向环形链表描述该结构并呈现整个自杀过程. 设计 首先要设计一个节点模型 class Node { int value; Node next; Node(int value) { this.value = value; } } 遍历并用 last 节点做成一个单向线性的链表,之后将自身的初始节点指向last.ne