1.、何为链表?
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。
2、链表适用的情景:
链表一般都在对数据的多少未知的情况下使用的,例如:记录学生的信息,因为不知道本期会有多少学生,如果申请一个大小为100的数组来存放学生的信息,而来的学生只有80或者超过100依然往该数组里存放,就会造成内存浪费或者访问了非法地址。中途一个学生走掉了,需要把相应信息删掉,对数组要进行很繁琐的一次操作。
而用链表不存在这些问题,来一个学生申请一段内存,这样不会造成内存浪费,学生走掉 释放该节点,并简单的把删掉节点的前一个节点指向删掉节点的下一个节点就OK了
链表有单链表,双联表,逆序链表,循环链表等
3、链表示例:(PHP)
1 <?php 2 /** 3 * 英雄类 4 */ 5 class Hero{ 6 public $no; 7 public $name; 8 public $nickname; 9 public $next=null; 10 public function __construct($no='',$name='',$nickname=''){ 11 $this->no=$no; 12 $this->name=$name; 13 $this->nickname=$nickname; 14 } 15 } 16 class LinkListDemo{ 17 public static function main(){ 18 $head=new Hero(); 19 $hero1=new Hero(1,"宋江","及时雨"); 20 $head->next=$hero1; 21 $hero2=new Hero(2,"卢俊义","玉麒麟"); 22 $hero1->next=$hero2; 23 LinkListDemo::showHeros($head); 24 } 25 /** 26 * 展示英雄 27 */ 28 public static function showHeros($head){ 29 $cur=$head; 30 while($cur->next!=null){ 31 echo "姓名:".$cur->next->name."<br/>"; 32 $cur=$cur->next; 33 } 34 } 35 36 } 37 38 LinkListDemo::main();
4、单链表翻转(面试中会经常遇到)
1 <?php 2 /** 3 * @file reverseLink.php 4 * @author showersun 5 * @date 2016/03/01 10:33:25 6 **/ 7 class Node{ 8 private $value; 9 private $next; 10 11 public function __construct($value=null){ 12 $this->value = $value; 13 } 14 public function getValue(){ 15 return $this->value; 16 } 17 public function setValue($value){ 18 $this->value = $value; 19 } 20 public function getNext(){ 21 return $this->next; 22 } 23 public function setNext($next){ 24 $this->next = $next; 25 } 26 } 27 //遍历,将当前节点的下一个节点缓存后更改当前节点指针 28 function reverse($head){ 29 if($head == null){ 30 return $head; 31 } 32 $pre = $head;//注意:对象的赋值 33 $cur = $head->getNext(); 34 $next = null; 35 while($cur != null){ 36 $next = $cur->getNext(); 37 $cur->setNext($pre); 38 $pre = $cur; 39 $cur = $next; 40 } 41 //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head 42 $head->setNext(null); 43 $head = $pre; 44 return $head; 45 } 46 //递归,在反转当前节点之前先反转后续节点 47 function reverse2($head){ 48 if (null == $head || null == $head->getNext()) { 49 return $head; 50 } 51 $reversedHead = reverse2($head->getNext()); 52 $head->getNext()->setNext($head); 53 $head->setNext(null); 54 return $reversedHead; 55 } 56 function test(){ 57 $head = new Node(0); 58 $tmp = null; 59 $cur = null; 60 // 构造一个长度为10的链表,保存头节点对象head 61 for($i=1;$i<10;$i++){ 62 $tmp = new Node($i); 63 if($i == 1){ 64 $head->setNext($tmp); 65 }else{ 66 $cur->setNext($tmp); 67 } 68 $cur = $tmp; 69 } 70 //print_r($head);exit; 71 $tmpHead = $head; 72 while($tmpHead != null){ 73 echo $tmpHead->getValue().' '; 74 $tmpHead = $tmpHead->getNext(); 75 } 76 echo " "; 77 //$head = reverse($head); 78 $head = reverse2($head); 79 while($head != null){ 80 echo $head->getValue().' '; 81 $head = $head->getNext(); 82 } 83 } 84 test(); 85 ?>
参考:https://blog.csdn.net/u013474436/article/details/50773736
https://www.cnblogs.com/taoshihan/p/5504239.html