php實現單,雙向鏈表,環形鏈表解決約瑟夫問題

傳智播客PHP學院 韓順平 PHP程序員玩轉算法第一季  http://php.itcast.cnphp

 

聊天篇:html

數學對咱們編程來講,重不重要?java

看你站在什麼樣的層次來講. 若是你應用程序開發,對數學要求不高mysql

可是,若是你開發系統軟件,好比(搜索/識別軟件[圖像,語言識別]/操做系統...)對數學高linux

建模.大量數學模型.android

 

老師啊啊。我是學C++的。麻煩,談哈對QT和MFC的見解嘛。前景什麼的,c++

記住 : 打好基礎,大有可爲!程序員

 

初中畢業能去傳智學習嗎?web

學習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

請發送到個人郵箱 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  你把結果給我計算出來!

 

問一個問題? 有沒有一個函數,能夠把個字符串當作一個運算字符來執行?

: 即便你使用 一個函數就能夠把這個算出,他的底層必定是堆棧來實現!

 

步驟

  1. 界面搞定.
  2. 思路->畫圖說明
  3. 如今處理一下多位數的運算.
  4. 處理連續是減號的運算符.

 

思考: 請你們思考如何給咱們的運算字符,帶上 ()

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

相關文章
相關標籤/搜索