php数据结构课程---3、队列(队列实现方法)
一、总结
一句话总结:
1、数据实现:适用于功能不复杂的情况
2、链表实现:受限链表,只能队头队尾操作:适用于功能复杂情况
1、队列的数组实现注意点?
array_push() + array_shift()
shift: [ʃɪft] :v. 转移;去除(污迹);n. 转移;改变
shift
英 [ʃɪft] 美 [ʃɪft]
- v. 转移;快速移动;变换;改变观点;推卸(责任);振作;移位;狼吞虎咽地吃;去除(污迹);销售,出售;换挡;轮班;含糊其辞,拐弯抹角
- n. 转移;改变,转变;手段;轮班;轮班职工;转换(键);(直筒式)连衣裙,内衣;计谋,诡计
1 数组实现队列 2 $arr = []; 3 array_push($arr,"张三"); 4 array_push($arr,"李四"); 5 array_push($arr,"王五"); 6 array_push($arr,"王六"); 7 8 while($data = array_shift($arr)){ 9 echo $data."<br>"; 10 }
2、队列的链表实现的注意点?
链表实现的队列可以增加各种函数来实现复杂操作
普通单链表结构 + push函数和shift函数
<?php class Node{ public $data; public $next; public function __construct($data,$next=null){ $this->data = $data; $this->next = $next; } } class Queue{ public $front = null; public $rear = null; public $size = 0; public function __construct(){ } public function push($data) { $n = new Node($data); if($this->front == null && $this->rear == null){ $this->front = $n; $this->rear = $n; }else{ $this->rear->next = $n; $this->rear = $n; } $this->size++; } public function shift() { if($this->front){ $this->size--; $data = $this->front->data; $this->front = $this->front->next; return $data; }else{ return null; } } } // $s = new Queue(); // $s->push("aaaa"); // $s->push("bb"); // $s->push("cc"); // $s->push("dd"); // $s->push("fifo"); // // echo $s->shift(); // while($data = $s->shift()){ // echo $data."<br>"; // }
3、在php中使用队列适合用什么?
在PHP中建议使用Spl库SplQueue(注意不是sql)
1 <?php 2 3 $queue = new SplQueue(); 4 $queue->enqueue('A'); 5 $queue->enqueue('B'); 6 $queue->enqueue('C'); 7 8 $queue->rewind(); 9 while($queue->valid()){ 10 echo $queue->current()," "; 11 $queue->next(); 12 } 13 14 print_r($queue); 15 $queue->dequeue(); //remove first one 16 print_r($queue); 17 18 ?> 19 Output 20 21 A 22 B 23 C 24 SplQueue Object 25 ( 26 [flags:SplDoublyLinkedList:private] => 4 27 [dllist:SplDoublyLinkedList:private] => Array 28 ( 29 [0] => A 30 [1] => B 31 [2] => C 32 ) 33 34 ) 35 SplQueue Object 36 ( 37 [flags:SplDoublyLinkedList:private] => 4 38 [dllist:SplDoublyLinkedList:private] => Array 39 ( 40 [0] => B 41 [1] => C 42 ) 43 44 )
4、php中统计算法执行时间的方法及函数?
microtime():其实超好记,其实不用记,时间函数是time(),计算程序时间肯定是微秒级的,微秒函数肯定是microtime()
$begin = microtime(); 算法段... $end = microtime()-$begin;
5、n个整数,最少选几个数,使和不小于s (穷举o(n^2),用队列的o(n))?
暴力:就是双重循环
队列(感觉不是很好,用优先队列取前几个比较好o(nlogn)):如果和不够,就增加队列中的元素,如何和够了,就减去队列之前的元素。队列中的元素的个数差不多就是结果(这样算有问题,只能得到近似解,难道最大的几个数一定在数组的某一段上么)
总结:普通队列能有什么东西,入队,出队,以及队列中的个数,仅此而已
暴力:
<?php // n个数列,最少选几个数,使和大于s,队列算法 o(n^2) $arr=[]; $sum = 0; $max = 10000; $min = 100; $s= 2500; $count = 0; //随机生成10000个数 for ($k=0; $k < $max ; $k++) { $arr[] = rand(0,1000); } $begin = microtime(); //两层for循环暴力穷举搜索结果 for ($i=0; $i <$max ; $i++) { $sum=$arr[$i]; for ($j=$i+1; $j <$max; $j++) { $count++; if($sum<=$s){ $sum+=$arr[$j]; }else{ $min=min($j-$i,$min); break; } } } $end = microtime()-$begin; echo "暴力穷举法 最少选择 $min 个数字,耗时 $end 毫秒,共执行 $count 循环。";
队列:
<?php // n个数列,最少选几个数,使和大于s,队列算法 o(n) $arr=[]; $sum = 0; $max = 10000; $min = 100; $count = 0; $s= 2500; $i = 0; $j = 1; //随机生成10000个数字 for ($k=0; $k < $max ; $k++) { $arr[] = rand(0,1000); } $queue = []; $begin = microtime(); $sum+=$arr[$i]; //当没有达到$max这个遍历次数时 while($i<$max && $j<$max){ $count++; //如果当前和小于所求 if($sum<=$s){ // array_push($queue,$arr[$j]); $sum+=$arr[$j]; $j++; }else{ //如果当前和大于所求 $min=min($j-$i,$min); // array_shift($queue); $sum-=$arr[$i]; $i++; } } $end = microtime()-$begin; echo "使用队列 最少需要选择 $min 数字, 耗时 $end 毫秒,共执行 $count 次!";
6、如何快速判断函数功能:或者说算法作用?
打印中间变量
最简单实例:比如n个整数,最少选几个数,使和不小于s (穷举o(n^2),用队列的o(n)) 的队列实现,最开始可以只选3个数
二、内容在总结中
n个整数,最少选几个数,使和不小于s (穷举o(n^2),用队列的o(n)) 的队列实现测试代码
//测试队列:n个数列,最少选几个数,使和大于s,队列算法 o(n) public function test_queue() { // n个数列,最少选几个数,使和大于s,队列算法 o(n) $arr=[]; $sum = 0; $max = 6; $min = 6; $count = 0; $s= 80; $i = 0; $j = 1; //随机生成10000个数字 for ($k=0; $k < $max ; $k++) { $arr[] = rand(0,100); } $queue = []; dump($arr); echo "sum:{$sum}<br>"; echo "arr[i]:{$arr[$i]}<br>"; $begin = microtime(); $sum+=$arr[$i]; //当没有达到$max这个遍历次数时 while($i<$max && $j<$max){ $count++; //如果当前和小于所求 if($sum<=$s){ // array_push($queue,$arr[$j]); $sum+=$arr[$j]; echo "---sum<=s---<br>"; echo "sum:{$sum}<br>"; echo "arr[j]:{$arr[$j]}<br>"; echo "i:{$i}<br>"; echo "j:{$j}<br>"; $j++; }else{ //如果当前和大于所求 echo "---else---<br>"; echo "sum:{$sum}<br>"; echo "arr[i]:{$arr[$i]}<br>"; echo "i:{$i}<br>"; echo "j:{$j}<br>"; $min=min($j-$i,$min); echo "min:{$min}<br>"; // array_shift($queue); $sum-=$arr[$i]; $i++; } echo "-sum:{$sum}<br><br>"; } $end = microtime()-$begin; echo "使用队列 最少需要选择 $min 数字, 耗时 $end 毫秒,共执行 $count 次!<br>"; }
测试的中间结果示例
array(6) { [0] => int(56) [1] => int(3) [2] => int(68) [3] => int(66) [4] => int(99) [5] => int(71) } sum:0 arr[i]:56 ---sum<=s--- sum:59 arr[j]:3 i:0 j:1 -sum:59 ---sum<=s--- sum:127 arr[j]:68 i:0 j:2 -sum:127 ---else--- sum:127 arr[i]:56 i:0 j:3 min:3 -sum:71 ---sum<=s--- sum:137 arr[j]:66 i:1 j:3 -sum:137 ---else--- sum:137 arr[i]:3 i:1 j:4 min:3 -sum:134 ---else--- sum:134 arr[i]:68 i:2 j:4 min:2 -sum:66 ---sum<=s--- sum:165 arr[j]:99 i:3 j:4 -sum:165 ---else--- sum:165 arr[i]:66 i:3 j:5 min:2 -sum:99 ---else--- sum:99 arr[i]:99 i:4 j:5 min:1 -sum:0 ---sum<=s--- sum:71 arr[j]:71 i:5 j:5 -sum:71 使用队列 最少需要选择 1 数字, 耗时 2.2000000000022E-5 毫秒,共执行 10 次!