数据结构与算法 - PHP

1.应用场景

学习数据结构和算法, 并且结合PHP, 了解PHP背后实现的原理.

2.学习/操作

1.复杂度分析和大O表示法

学习数据结构和算法要从复杂度分析说起。算法复杂度包括时间复杂度和空间复杂度,两者中又以时间复杂度相对重要,因为就 Web 应用而言,我们常见的性能优化策略都是以空间换时间,比如缓存系统就是如此。

时间复杂度表示代码执行时间随数据规模增长的变化趋势,表示方法图所示:

即大O表示法,我们在分析时间复杂度的时候往往遵循以下原则:

  • 1、只关注循环执行次数最多的一段代码;
  • 2、加法法则:总复杂度等于量级最大的那段代码的复杂度;
  • 3、乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积。

因此,如果分析某个算法的时间复杂度是

 

T(n) = O(2n+2)

或者

T(n) = O(2n^2 +2n+3)

则公式中的低阶、常量、系数三部分都可以忽略,即:

T(n) = O(n)

T(n) = O(n^2)

 

常见时间复杂度如下所示:

数据结构与算法 - PHP_第1张图片图片来自于极客时间-算法专栏

时间复杂度里细分起来又有最好、最坏、平均情况时间复杂度之分:

  • 1、最好情况时间复杂度就是在最理想的情况下,执行这段代码的时间复杂度;
  • 2、最坏情况时间复杂度就是在最糟糕的情况下,执行这段代码的时间复杂度;
  • 3、平均情况时间复杂度顾名思义就是结合概率论分析从最好到最坏每种情况平均下来的加权平均时间复杂度

一般而言,我们关注时间复杂度就够了,只有特别严苛条件下或者复杂度相同的情况下,我们才会进一步区分最好、最坏、平均复杂.

 

 

2. 数组

数组(Array)是一种线性表数据结构,它用一组连续的内存空间,来存储一组具有相同类型的数据。

如果你学习过 C 语言,应该对这段定义很熟悉,但是在 PHP 这种动态语言中,因为数组底层是通过散列表(后面我们会介绍这个数据结构)实现的,所以功能异常强大这段常规的数组定义在 PHP 中并不成立,PHP 的数组可以存储任何类型数据,如果与 Java 对比的话,PHP 数组集成了 Java 的数组、List、Set、Map 于一身,所以写代码的效率比 Java 高了几个量级。

 

抛开 PHP 或 JavaScript 这种动态语言,对于传统的数组,比如 C 语言和 Java 中的数组,在使用之前都需要声明数组存储数据的类型和数组的大小,数组的优点是可以通过下标值随机访问数组内的任何元素,算法复杂度是 O(1),非常高效,但是缺点是删除/插入元素比较费劲,以删除为例,需要在删除某个元素后,将后续元素都往前移一位,如果是插入,则需要将插入位置之后的元素都往后移,所以对数组的插入/删除而言,算法复杂度是 O(n),当然了,这个是针对 C / Java 这种语言而言,PHP 不受此约束,因为它不是传统一样上的数组。

 

 

备注:

数据搬移操作, 是语言底层做的, 并不是说你在写Java、C 的代码时要这么做

那就不叫高级语言了 叫汇编了 但是底层做不代表没有做.

 

 

3. 链表

链表,和数组不同,链表并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,如图所示:

https://xueyuanjun.com/post/20948

数据结构与算法 - PHP_第2张图片

类别:

单链表

循环链表[单向]

双向链表

双向循环链表  //用的最多

 

通过数组函数模拟实现单链表

在 PHP 中由于没有指针,我们可以借助数组的 nextcurrentkey 等函数实现链表这个数据结构:

/**
 * 通过 PHP 数组模拟实现单链表
 */
class LinkedList
{
    private $list = [];

    // 获取链表指定位置的元素值,从0开始
    public function get($index)
    {
        $value = NULL;
        while (current($this->list)) {
            if (key($this->list) == $index) {
                $value = current($this->list);
            }
            next($this->list);
        }
        reset($this->list);
        return $value;
    }

    // 在链表指定位置插入值,默认插到链表头部
    public function add($value, $index = 0)
    {
        array_splice($this->list, $index, 0, $value);
    }

    // 从链表指定位置删除元素
    public function remove($index)
    {
        array_splice($this->list, $index, 1);
    }

    public function isEmpty()
    {
        return !next($this->list);
    }

    public function size()
    {
        return count($this->list);
    }
}

$linkedList = new LinkedList();
$linkedList->add(4);
$linkedList->add(5);
$linkedList->add(3);
print $linkedList->get(1);   # 输出5
$linkedList->add(1, 1);      # 在结点1的位置上插入1
print $linkedList->get(1);   # 输出1
$linkedList->remove(1);      # 移除结点1上的元素
print $linkedList->get(1);   # 输出5
print $linkedList->size();   # 输出3

写下这段代码主要帮助你理解链表的实现思路,在 PHP 中,数组集成了所有数据结构,如数组、List、散列表、Map等,而且由于 PHP 不支持指针,所以不能实现真正的链表,比如在插入、删除的时候指针指向的变动无法实现,只能笼统通过 array_splice 函数实现元素插入和删除,也就无法区别实现单向链表、双向链表和循环链表。

不过 PHP 底层提供的 SPL 库中包含了一个双向链表的实现:http://php.net/manual/zh/class.spldoublylinkedlist.php,感兴趣的可以去看看。

 

 

 

 

 

后续补充

...

3.问题

TBD

4.参考

https://xueyuanjun.com/books/data-structure-and-algorithms  //数据结构与算法[PHP]

https://blog.csdn.net/william_n/article/details/100174887  //数据结构与算法之美

https://blog.csdn.net/william_n/article/details/103092795  //数据结构与算法之美-问题收集

后续补充

...

  

你可能感兴趣的:(数据结构-DATA,STRUCTURE,PHP,数据结构与算法,PHP)