PHP数据结构

PHP优先队列、二叉堆、大顶堆、小顶堆

2021-12-07  本文已影响0人  江月照我眠

一 、基本数据结构

堆:

将根结点最大的堆叫做最大堆、大顶堆或大根堆,根结点最小的堆叫做最小堆、小顶堆或小根堆。常见的堆有二叉堆、斐波那契堆
通常堆顶节点都是最大或者最小的,在解决特殊问题时,先弹出堆顶元素非常有优势

栈:

先进后出(FILO),就像一个敞口向上的容器,只能将后进入容器的先弹出。

队列:

先进先出(FIFO),跟栈相反,队列就像一根上下贯通的水管,只能将先流入水管的水流出去。

二、优先级队列

优先队列也是一种数据结构,通过加权值进行排序,PHP核心库提供了SplPriorityQueue对象来实现。
优先队列内部是用Heap:堆这种数据结构来实现的,默认是大顶堆(MaxHeap)。

1. 常规用法(大顶堆)
$queue = new SplPriorityQueue;

// 插入堆,并自动筛选和排序
// 接受2个参数,insert(值, 优先级)
$queue->insert('A', 3);
$queue->insert('B', 9);
$queue->insert('C', 2);
$queue->insert('D', 5);

// 堆中元素的个数
$count = $queue->count(); // 此时为4

// 返回堆顶的节点
$top = $queue->top(); // 堆不变

/**
* 设置元素出队模式
* SplPriorityQueue::EXTR_DATA 仅提取值
* SplPriorityQueue::EXTR_PRIORITY 仅提取优先级
* SplPriorityQueue::EXTR_BOTH 提取数组包含值和优先级
*/
$queue->setExtractFlag(SplPriorityQueue::EXTR_BOTH);

// 从堆顶提取元素,并重新筛选和排序
$queue->extract(); // 此时B被取出,堆顶元素重置为D
$queue->extract(); // 此时D被取出,堆顶元素重置为A
$queue->extract(); // 此时A被取出,堆顶元素重置为C
$queue->extract(); // 此时C被取出,堆中元素全部取出

// 判断堆是否为空
$status = $queue->isEmpty(); // 结果为true

// 迭代指针相关

// 因为优先队列是堆实现的,所以rewind实际没什么用,他永远指向堆顶指针,current也永远等于堆顶的值
// 故而extract相当于current(返回当前节点)和next(指向下一个节点)两个操作

// 返回当前节点
$current = $queue->current();

// 指针指向下一个节点
$queue->next();

// 返回堆中堆中是否还有节点
while ($queue->valid()) {
    $current = $queue->current();
    $queue->next();
}

2. 改成小顶堆(MinHeap)

优先队列改成小顶堆,需要重写compare方法,将比较值对调,即可切换小顶堆和大顶堆。

/*
 * 小顶堆
 */
class MyMinHeap extends SplPriorityQueue {
    function compare($value1, $value2) {
        // if ($value1 === $value1) return 0;
        // return $value1 < $value2 ? -1 : 1; 
        // return $value1 - $value2; // 高优先级优先
        return $value2 - $value1; // 低优先级优先
    }
}

$queue = new MyMinHeap;

// 插入堆,并自动筛选和排序
// insert接受2个参数,key在前,value在后,vaue为排序的权重值
$queue->insert('A', 3);
$queue->insert('B', 9);
$queue->insert('C', 2);
$queue->insert('D', 5);

$queue->extract(); // 此时C被取出,堆顶元素重置为A
$queue->extract(); // 此时A被取出,堆顶元素重置为D
$queue->extract(); // 此时D被取出,堆顶元素重置为B
$queue->extract(); // 此时B被取出,堆中元素全部取出

$status = $queue->isEmpty(); // 结果为true

三、堆、大顶堆和小顶堆

堆就是为了实现优先队列而设计的一种数据结构,它分为大顶堆和小顶堆,PHP核心库提供了大顶堆SplMaxHeap小顶堆SplMinHeap两种类可供直接使用,他们都是由SplHeap抽象类实现的。

/**
 * 自定义:最小堆/小顶堆
 * 低优先级优先弹出
 * 等同于系统自带的SplMinHeap
 */
class MyMinHeap extends SplHeap
{
    // 比较元素,以便在筛选时将它们正确地放在堆中,
    // 如果value1大于value2则为正整数,如果相等则为0,否则为负整数
    function compare($value1, $value2) { 
        return $value2 - $value1;
    } 
}

/**
 * 自定义:最大堆/大顶堆
 * 高优先级优先弹出
 * 等同于系统自带的SplMaxHeap
 */
class MyMaxHeap extends SplHeap
{
    // 比较元素,以便在筛选时将它们正确地放在堆中,
    // 如果value1小于value2则为正整数,如果相等则为0,否则为负整数
    function compare($value1, $value2) { 
        return $value1 - $value2;
    } 
}

$minHeap = new MyMinHeap;
// 插入元素,insert(值)
$minHeap->insert(3);
$minHeap->insert(2);
$minHeap->insert(4);
$minHeap->insert(1);
// 取出元素
$minHeap->extract(); // 1被取出
$minHeap->extract(); // 2被取出
$minHeap->extract(); // 3被取出
$minHeap->extract(); // 4被取出

$maxHeap = new MyMaxHeap;
// 插入元素
$maxHeap->insert(3);
$maxHeap->insert(2);
$maxHeap->insert(4);
$maxHeap->insert(1);
// 取出元素
$maxHeap->extract(); // 4被取出
$maxHeap->extract(); // 3被取出
$maxHeap->extract(); // 2被取出
$maxHeap->extract(); // 1被取出

/**
 * 自定义:最小堆/小顶堆
 * 低优先级优先弹出
 * 等同于系统自带的SplMinHeap
 */
class MyMinHeap extends SplHeap
{
    function compare($arr1, $arr2) { 
        $value1 = array_values($arr1);
        $value2 = array_values($arr2);
        if ($value2[0] === $value1[0]) return 0;
        return $value2[0] < $value1[0] ? -1 : 1;
    } 
}

/**
 * 自定义:最大堆/大顶堆
 * 高优先级优先弹出
 * 等同于系统自带的SplMaxHeap
 */
class MyMaxHeap extends SplHeap
{
    function compare($arr1, $arr2) { 
        $value1 = array_values($arr1);
        $value2 = array_values($arr2);
        // if ($value2[0] === $value1[0]) return 0;
        // return $value2[0] > $value1[0] ? -1 : 1;// 高优先级优先弹出
        return $value1[0] - $value2[0];
    } 
}

$minHeap = new MyMinHeap;
// 插入元素,insert(值)
$minHeap->insert(['A' => 3]);
$minHeap->insert(['B' => 2]);
$minHeap->insert(['C' => 4]);
$minHeap->insert(['D' => 1]);
// 取出元素
$minHeap->extract(); // D被取出
$minHeap->extract(); // B被取出
$minHeap->extract(); // A被取出
$minHeap->extract(); // C被取出

$maxHeap = new MyMaxHeap;
// 插入元素
$maxHeap->insert(['A' => 3]);
$maxHeap->insert(['B' => 2]);
$maxHeap->insert(['C' => 4]);
$maxHeap->insert(['D' => 1]);
// 取出元素
$maxHeap->extract(); // C被取出
$maxHeap->extract(); // A被取出
$maxHeap->extract(); // B被取出
$maxHeap->extract(); // D被取出

总结:

上一篇 下一篇

猜你喜欢

热点阅读