跳跃表实现 发表于 2020-12-04 | 更新于 2024-09-02 | 分类于 PHP 本文字数: 25k | 阅读时长 ≈ 23 分钟 思考并回答以下问题: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173class Node{ private $id; public $value; public $level; public $forward = []; public function __construct($value, $level) { $this->id = uniqid(); $this->level = $level; $this->value = $value; for ($i = 0; $i < $level; $i++) { $this->forward[$i] = 0; } } public function getID() { return $this->id; }}class SkipList{ private $maxLevel; public $nodePool = []; public $header; public function __construct($maxLevel) { $this->maxLevel = $maxLevel; $header = new Node(-1, $maxLevel); $this->addToNodePool($header->getID(), $header); $this->header = $header->getID(); } public function addToNodePool($id, $object) { $this->nodePool[$id] = $object; } /** * @param $id * @return Node */ public function getFromNodePool($id) { return isset($this->nodePool[$id]) ? $this->nodePool[$id] : null; } public function insert($value) { $visitTrace = []; $count = 0; $tmp = $this->getFromNodePool($this->header); for ($i = $this->maxLevel - 1; $i >= 0; $i--) { while ($tmp && $tmp->forward[$i]) { $count++; if ($count > 20) { break; } $forward = $this->getFromNodePool($tmp->forward[$i]); if ($forward->value < $value) { $tmp = $forward; } else if ($forward->value > $value) { break; } else { return false; } } if ($tmp) { $visitTrace[$i] = $tmp->getID(); } } $level = $this->randomLevel(); $newNode = new Node($value, $level); $this->addToNodePool($newNode->getID(), $newNode); for ($i = 0; $i < $level; $i++) { $trace = $this->getFromNodePool($visitTrace[$i]); $newNode->forward[$i] = $trace->forward[$i]; $trace->forward[$i] = $newNode->getID(); } return true; } public function find($value) { $tmp = $this->getFromNodePool($this->header); $count = 0; for ($i = $this->maxLevel - 1; $i >= 0; $i--) { while ($tmp && $tmp->forward[$i]) { $count++; if ($count > 20) { break; } $forward = $this->getFromNodePool($tmp->forward[$i]); if ($forward->value < $value) { $tmp = $forward; } else if ($forward->value > $value) { break; } else { return true; } } } return false; } private function randomLevel() { $level = 1; if (rand(0, 1) && $level < $this->maxLevel) { $level++; } return $level; }}$testData = [898888, 300, 234, 123, 333, 456, 23, 99];$skipList = new SkipList(3);foreach ($testData as $value) { $skipList->insert($value);}$test = [898888, 300, 234, 123, 333, 456, 23, 99, 100, 111];foreach ($test as $value) { $result = $skipList->find($value); if (in_array($value, $testData) && in_array($value, $test)) { if ($result) { echo '正确<br>'; } else { echo '错误<br>'; } } else { if ($result) { echo '错误<br>'; } else { echo '正确<br>'; } }}