PHP数据结构(二)——链式结构线性表

PHP数据结构(二)——链式结构线性表

(原创内容,转载请注明来源,谢谢)

线性表分为顺序结构和链式结构,链式结构里每一个数据单元除了有数据之外,还有一个空间指向下一个数据的位置(双向链表里面还有一个指向前一个单元的位置)。

链式结构根据其方向性分为单向链表和双向链表,根据其循环性分为普通链表和循环链表。

单向链表:每个数据单元有数据和指向后继数据单元的位置。

双向链表:每个数据单元有数据和指向前驱以及后继单元的位置。

循环链表:链表的最后一个数据指向链表的第一个数据。

普通链表:链表的最后一个数据指向空(Null)。

另外,通常链表里面还有两个概念:

1:头指针,表示链表的开始,本身没有数据内容,指向链表第一个数据。

2:尾指针,表示链表的结束,本身没有数据内容,指向null(循环链表中指向头指针)。

优点:由于链表的每个单元之间的连接是根据指向的,因此对于链表的插入和删除操作较为方便,只需要修改链表中的指向即可。

缺点:查询、修改链表中的某个元素时,不好查找,需要遍历整个链表。对于单向链表,甚至链表前面的元素都无法快速查找,需要从头遍历。

用PHP实现双向循环链表的生成、增删改查。

结果如下:

源代码如下:

<?php
class chain{
         //数值、前驱、后继
         public $chaintable;
         public $prev;
         public $next;
         //构造
         public function__construct($chaintable=null){
                   $this->chaintable =$chaintable;
         }
         //生成链表
         public function generate($arrChain){
                   $tail = new chain();
                   $this->prev = $tail;
                   $tail->next = $this;
                   $cur = $this;
                   foreach($arrChain as $item){
                            $tmp = newchain($item);
                            $cur->next =$tmp;
                            $tmp->prev =$cur;
                            $cur = $tmp;
                   }
                   $cur->next = $tail;
                   $tail->prev = $cur;
         }
         //展示链表
         public function show(){
                   $tmp = $this;
                   while($tmp->next->chaintable!=null){
                            echo '<br/>'.$tmp->next->chaintable;
                            $tmp =$tmp->next;
                   }                
         }
         //获取链表长度
         public function length(){
                   $i = 0;
                   $tmp = $this;
                   while($tmp->next->chaintable!=null){
                            $i++;
                            $tmp = $tmp->next;
                   }                
                   return $i;
         }
         //查找第i个元素
         public function search($i){
                   $tmp = $this;
                   $chain_length =$tmp->length();
                   if($i<=0 ||$i>$chain_length){
                            echo '<br />元素超出链表长度';
                   }else{
                            $j = 0;
                            while($j<$i){
                                     $j++;
                                     $tmp =$tmp->next;
                            }
                            echo '<br />第'.$i.'个元素是:'.$tmp->chaintable;
                   }
         }
         //合并有序链表
         public function merge($old_chain,$new_chain){
                   $old_length =$old_chain->length();
                   $new_length =$new_chain->length();
                   $old_chain =$old_chain->next;//跳过头部
                   $new_chain = $new_chain->next;
                   $i = 1;
                   $j = 1;
                   $k = 1;//循环次数
                   $final_chain = new chain();
                   $tmp = new chain();
                   while($i<=$old_length&& $j<=$new_length){
                            if($old_chain->chaintable<= $new_chain->chaintable){
                                     $old_chain->prev= $final_chain;
                                     $final_chain->next= $old_chain;
                                     $final_chain= $old_chain;//***把final_chain的指针往后一步 
                                     $old_chain= $old_chain->next;
                                     $i++;
                            }else{
                                     $new_chain->prev= $final_chain;
                                     $final_chain->next= $new_chain;
                                     $final_chain= $new_chain;//***把final_chain的指针往后一步 
                                     $new_chain= $new_chain->next;
                                     $j++;                                    
                            }
                            $k++;
                   }
                   if($i <= $old_length){
                            $final_chain->next= $old_chain;
                            $old_chain->prev= $final_chain;
                   }else{
                            $final_chain->next= $new_chain;
                            $new_chain->prev= $final_chain;                    
                  }
                   echo '<br />合并成功';
                   return $final_chain;
         }
         //修改链表第i个元素
         public function modify($i, $data){
                   $tmp = $this;
                   $chain_length =$tmp->length();
                   if($i<=0 ||$i>$chain_length){
                            echo '<br />元素超出链表长度';
                   }else{
                            $j = 0;
                            while($j<$i){
                                     $j++;
                                     $tmp =$tmp->next;
                            }
                            $tmp->chaintable= $data;
                            echo '<br />修改成功';
                   }                
         }
         //删除链表第i个元素
         public function delete($i){
                   $tmp = $this;
                   $chain_length =$tmp->length();
                   if($i<=0 ||$i>$chain_length){
                            echo '<br />元素超出链表长度';
                   }else{
                            $j = 0;
                            while($j<$i-1){//找到第i个元素的前一个元素
                                     $j++;
                                     $tmp =$tmp->next;
                            }
                            $tmp->next =$tmp->next->next;
                            $tmp->next->next->prev= $tmp;
                            echo '<br />删除成功';
                   }                
         }
}
$my_chain = newchain();
$my_chain->generate(array(1,3,7,9,12,15,16));
$my_chain->show();
$chain_length =$my_chain->length();
echo '<br/>链表长度:'.$chain_length;
$my_chain->search(2);
$new_chain = newchain();
$new_chain->generate(array(2,3,5,8,13,19,20));
$my_chain->merge($my_chain,$new_chain);
$my_chain->show();
$my_chain->modify(3,6);
$my_chain->show();
$my_chain->delete(5);
$my_chain->show();
?>

—— written by linhxx 2017.06.14

相关阅读:

PHP数据结构(一)——顺序结构线性表

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

静态成员函数和非静态成员函数的区别?

一个静态成员函数不与任何对象相联系,故不能对非静态成员进行默认访问。 它们的根本区别在于静态成员函数没有this指针,而非静态成员函数有一个指向当前对象的指针t...

1899
来自专栏和蔼的张星的图像处理专栏

6. 合并排序数组

合并两个排序的整数数组A和B变成一个新的数组。 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 最简单...

932
来自专栏javathings

为什么说 Java 的泛型是伪泛型?

Java 的泛型是伪泛型, 也就是骗骗编译器的。运行期的泛型类型,被擦除了,因此,在运行期,ArrayList<String> 和 ArrayList<int>...

872
来自专栏Python小屋

Python元组与列表的相同点与区别

列表和元组都属于有序序列,支持使用双向索引访问其中的元素、使用内置函数len()统计元素个数、使用运算符in测试是否包含某个元素、使用count()方法统计指定...

2656
来自专栏武军超python专栏

2018年8月23日python中列表的高级操作:列表推导式,列表生成器,列表迭代器

列表在我们平常的编程中经常会用到,多用于临时存储一些程序需要的数据, 向列表中添加数据时,有多种方式: 1.数据少的话直接定义列表中的数据 my1 = [...

1003
来自专栏服务端技术杂谈

Golang可变参数

既然我们知道了可变参数会被转换成切片,那么通过go语法糖,可以将一个存在的分配当作可变参数的参数。

793
来自专栏青枫的专栏

java面试题

当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)...

821
来自专栏蓝天

shell数组

$ A=(a b c def) ================================================== $ echo ${A[@...

954
来自专栏服务端思维

你看懂“箭头函数”了么?

ES6 允许使用“箭头”(=>)定义函数。如果了解 Java 的 Lambda 表达式,回过头来理解 ES6 的箭头函数,就非常好理解了。

652
来自专栏狮乐园

javascript原型链-review

虽然现在es8都已经在预发布阶段了,但是无论发布到es几,其本身的运作原理都是一样的。

451

扫码关注云+社区