//二分查找
$data = array(4,6,7,8,14,55,67,145,218,237,284);
function binarySearch($data, $num){
$count = count($data);
$high = $count - 1;
$low = 0;
while ($low <= $high){
$mid = floor(($high + $low) / 2);
//$mid = floor($low + ($num - $data[$low]) / ($data[$high] - $data[$low]) * ($high - $low));//插值查找
if($num == $data[$mid]){
return $mid;
}elseif ($num > $data[$mid]){
$low = $mid + 1;
}else{
$high = $mid -1;
}
}
return false;
}
$res = binarySearch($data, 4);
var_dump($res); //1
插值查找(二分查找优化)
首先考虑一个新问题,为什么一定要是折半,而不是折四分之一或者折更多呢?
打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再让你查“zoo”,你又怎么查?很显然,这里你绝对不会是从中间开始查起,而是有一定目的的往前或往后翻。
同样的,比如要在取值范围1 ~ 10000 之间 100 个元素从小到大均匀分布的数组中查找5, 我们自然会考虑从数组下标较小的开始查找。
经过以上分析,折半查找这种查找方式,还是有改进空间的,并不一定是折半的!
mid = (low+high)/ 2, 即 mid = low + 1/2 * (high - low);
改进为下面的计算机方案(不知道具体过程):mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low),也就是将上述的比例参数1/2改进了,根据关键字在整个有序表中所处的位置,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
分析:从时间复杂度上来看,它也是o(n),但是对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。反之,数组中如果分布非常不均匀,那么差值查找未必是很合适的选择。
class node{
public $value;
public $left;
public $right;
public $parent;
public function __construct($data){
$this->value = $data;
}
}
class searchtree{
public $root = null;
public $size = 0;
public $depth = 0;
public function __construct($value){
$this->root = new node($value);
$this->size++;
$this->depth++;
}
public function addnode($array){
foreach ($array as $key=> $value) {
$current = $this->root;
$parent = null;
$currentdepth = 1;
while($current !== null){
$parent = $current;
if($current->value == $value){
continue 2;
}
elseif($current->value > $value){
$current = $current->left;
}else{
$current = $current->right;
}
$currentdepth++;
}
$node = new node($value);
$node->parent = $parent;
if($parent->value > $value){
$parent->left = $node;
}else{
$parent->right = $node;
}
if($this->depth < $currentdepth){
$this->depth++;
}
$this->size++;
}
return true;
}
public function successor($node){
if ($node->right !== null) {
$current = $node->right;
while($current->left !== null){
$current = $current->left;
}
return $current;
}
$parent = $node->parent;
while ($parent !== null && $node = $parent->right) {
$node = $parent;
$parent = $parent->parent;
}
return $parent;
}
public function delnode($value) {
$node = $this->search($value);
if ($node->left === null || $node->right === null) {
#如果待删除结点无子节点或只有一个子节点,则c = dnode
$current = $node;
} else {
#如果待删除结点有两个子节点,c置为dnode的直接后继,以待最后将待删除结点的值换为其后继的值
$current = $this->successor($node);
}
//print_r($current->value);exit;
if ($current->left !== null) {
$s = $current->left;
} else {
$s = $current->right;
}
if ($s !== null) { #将c的子节点的父母结点置为c的父母结点,此处c只可能有1个子节点,因为如果c有两个子节点,则c不可能是dnode的直接后继
$s->parent = $current->parent;
}
if ($current->parent === null) { #如果c的父母为空,说明c=dnode是根节点,删除根节点后直接将根节点置为根节点的子节点,此处dnode是根节点,且拥有两个子节点,则c是dnode的后继结点,c的父母就不会为空,就不会进入这个if
$this->root = $s;
} else if ($current == $current->parent->left) { #如果c是其父节点的左右子节点,则将c父母的左右子节点置为c的左右子节点
$current->parent->left = $s;
} else {
$current->parent->right = $s;
}
#如果c!=dnode,说明c是dnode的后继结点,交换c和dnode的key值
if ($current != $node) {
$node->value = $current->value;
}
#返回成功
return true;
}
public function search($value){
$current = $this->root;
while($current !== null){
if($current->value == $value){
return $current;
}
elseif($current->value > $value){
$current = $current->left;
}else{
$current = $current->right;
}
}
return false;
}
}
$tree = new searchtree(300);
$tree->addnode(array(124,360,250,110,260,270,160,350,370,320,352));
$tree->delnode(300);
print_r($tree);
?>
//单个节点
class node {
//初始化变量,包括存储的内容 和 下一个数据的指针
public $id = 0;
public $data = '';
public $next = null;
//构造函数,设置存储内容的数据
public function __construct($id,$nodedata){
$this->id = $id;
$this->data = $nodedata;
}
}
class singleLink {
public $head = '';
public $size = 0;
public function insert($id,$value,$prenodeid = 0){
$node = new node($id,$value);
//空链表,直接添加
if ($this->size == 0){
$this->head = $node;
} elseif ($prenodeid == 0) {
//如果不是空链表,且并没有指定在某一个节点前添加
//则在当前节点前添加
$node->next = $this->head;
$this->head = $node;
} else {
//在某一节点后添加新节点
$cruntnode = $this->head;
while($cruntnode->next != null ){
if($cruntnode->next->id == $prenodeid){
$node->next = $cruntnode->next;
$cruntnode->next = $node;
break;
}
$cruntnode = $cruntnode->next;
}
}
$this->size++;
return $this;
}
public function edit($id,$value){
$flag = false;
$current = $this->head;
while(@$current->id !=null){
if($current->id == $id){
$current->data = $value;
$flag = true;
break;
}
$current = $current->next;
}
return $flag;
}
public function get($id=0){
$current = $this->head;
while(@$current->id !=null){
if($id !=0 && $current->id==$id){
$node = $current;
break;
} else {
$node[] = array($current->id,$current->data);
}
$current = $current->next;
}
return $node;
}
public function sort(){
}
public function delete($id){
$flag = false;
$current = $this->head;
while(@$current->id !=null){
if($current->next->id == $id){
$current->next = $current->next->next;
$this->size--;
$flag = true;
break;
}
$current = $current->next;
}
return $flag;
}
}
$linklist = new singleLink();
$linklist->insert(1,'hello');
$linklist->insert(2,'my');
$linklist->insert(3,'love');
$linklist->insert(4,'haha4');
$linklist->insert(5,'haha5');
$linklist->insert(6,'haha6');
$linklist->insert(7,'haha7');
$linklist->delete(5);
$linklist->insert(8,'haha8')->insert(9,'haha9')->insert(10,'haha10')->insert(11,'haha11');
var_dump($linklist);
?>
$list = array(39, 38, 22, 45, 23, 67, 31, 15, 41);
$count = count($list);
$num = 0;
$newlist = bubbleSort($list);
print_r($newlist);
function bubbleSort($numbers){
$cnt = count($numbers);
for($i=0;$i<$cnt-1;$i++){//循环比较
for($j=0;$j<$cnt-1-$i;$j++){
if($numbers[$j]>$numbers[$j+1]){//执行交换
$temp=$numbers[$j+1];
$numbers[$j+1]=$numbers[$j];
$numbers[$j]=$temp;
}
}
}
return $numbers;
}
$list = array(10,3,5,7,11,45,64,74,23,21,6);
$return = quicksort($list);
var_dump($return);exit;
function quicksort($arr){
if(count($arr)>1){
$k=$arr[0];
$x=array();
$y=array();
$size=count($arr);
for($i=1;$i<$size;$i++){
if($arr[$i]<=$k){
$x[]=$arr[$i];
}else{
$y[]=$arr[$i];
}
}
$x=quicksort($x);
$y=quicksort($y);
return array_merge($x,array($k),$y);
}else{
return$arr;
}
}
$list = array(10,3,5,7,18,11,45,64,74,23,21,6);
$list = select_sort($list);
print_r($list);
function select_sort($list){
$count = count($list);
for ($i=0; $i < $count; $i++) {
$k = $i;
for ($j=$i+1; $j < $count; $j++) {
if($list[$k] > $list[$j]){
$k = $j;
}
}
if($k != $i){
$tem = $list[$i];
$list[$i] = $list[$k];
$list[$k] = $tem;
}
}
return $list;
}