邢栋博客
邢栋博客,Action博客,记录工作和生活中的点点滴滴
PHP 两个有序数组合并成一个有序数组
标签:
算法
<?php $a = [1,3,5,7,9,11]; $b = [2,4,6,8,10]; function test_sort($a,$b){ $c = []; $aCount = count($a); $bCount = count($b); $i = $j = 0; while($i < $aCount && $j < $bCount){ if($a[$i] > $b[$j]){ $c[] = $b[$j]; $j++; }elseif($a[$i] < $b[$j]){ $c[] = $a[$i]; $i++; }else{ $c[] = $a[$i]; $c[] = $b[$j]; $i++; $j++; } } while($i < $aCount){ $c[] = $a[$i]; $i++; } while($j < $bCount){ $c[] = $a[$j]; $j++; } return $c; } function test_sort2($a,$b){ $c = []; $aCount = count($a); $bCount = count($b); $i = $j = 0; while($i < $aCount || $j < $bCount){ if($i < $aCount && $j < $bCount){ if($a[$i] > $b[$j]){ $c[] = $b[$j]; $j++; }elseif($a[$i] < $b[$j]){ $c[] = $a[$i]; $i++; }else{ $c[] = $a[$i]; $c[] = $b[$j]; $i++; $j++; } }elseif($i < $aCount && $j >= $bCount){ $c[] = $a[$i]; $i++; }elseif($i >= $aCount && $j < $bCount){ $c[] = $b[$j]; $j++; } } return $c; } $res = test_sort2($a,$b); print_r($res);
php下正则匹配大字符串失败问题
问题描述:
在使用php函数preg_match匹配大字符串的时候匹配失败,而删除一半数据,则匹配成功,
解决过程:
于是在匹配结束后,调用preg_last_error()函数,查看失败原因,返回的是6,6对应的错误原因是PREG_JIT_STACKLIMIT_ERROR,
原来当字符串太大的时候,栈空间满了,直接就出错了,于是在匹配前加一下代码
解决查找的资料
1、深悉正则(pcre)最大回溯/递归限制(https://www.laruence.com/2010/06/08/1579.html)
在使用php函数preg_match匹配大字符串的时候匹配失败,而删除一半数据,则匹配成功,
解决过程:
于是在匹配结束后,调用preg_last_error()函数,查看失败原因,返回的是6,6对应的错误原因是PREG_JIT_STACKLIMIT_ERROR,
原来当字符串太大的时候,栈空间满了,直接就出错了,于是在匹配前加一下代码
ini_set('pcre.jit', 0);
解决查找的资料
1、深悉正则(pcre)最大回溯/递归限制(https://www.laruence.com/2010/06/08/1579.html)
php-bc数据函数
标签:
=====bcadd — 2个任意精度数字的加法计算=====
<?php $a = '1.234'; $b = '5'; echo bcadd($a, $b); // 6 echo bcadd($a, $b, 4); // 6.2340 ?>=====bccomp — 比较两个任意精度的数字=====
<?php echo bccomp('1', '2') . "\n"; // -1 echo bccomp('1.00001', '1', 3); // 0 echo bccomp('1.00001', '1', 5); // 1 ?>=====bcdiv — 2个任意精度的数字除法计算=====
<?php echo bcdiv('105', '6.55957', 3); // 16.007 ?>=====bcmod — 对一个任意精度数字取模=====
<?php echo bcmod('4', '2'); // 0 echo bcmod('2', '4'); // 2 ?>=====bcmul — 2个任意精度数字乘法计算=====
<?php echo bcmul('1.34747474747', '35', 3); // 47.161 echo bcmul('2', '4'); // 8 ?>=====bcpow — 任意精度数字的乘方=====
<?php echo bcpow('4.2', '3', 2); // 74.08 ?>=====bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus=====
<?php $a = bcpowmod($x, $y, $mod); $b = bcmod(bcpow($x, $y), $mod); // $a and $b are equal to each other. ?>=====bcscale — 设置所有bc数学函数的默认小数点保留位数=====
<?php // default scale : 3 bcscale(3); echo bcdiv('105', '6.55957'); // 16.007 // this is the same without bcscale() echo bcdiv('105', '6.55957', 3); // 16.007 ?>=====bcsqrt — 任意精度数字的二次方根=====
<?php echo bcsqrt('2', 3); // 1.414 ?>=====bcsub — 2个任意精度数字的减法=====
<?php $a = '1.234'; $b = '5'; echo bcsub($a, $b); // -3 echo bcsub($a, $b, 4); // -3.7660 ?>
关于redis pipeline
=====为什么需要 pipeline ?=====
Redis 的工作过程是基于 请求/响应 模式的。正常情况下,客户端发送一个命令,等待 Redis 应答;Redis 接收到命令,处理后应答。请求发出到响应的时间叫做往返时间,即 RTT(Round Time Trip)。在这种情况下,如果需要执行大量的命令,就需要等待上一条命令应答后再执行。这中间不仅仅多了许多次 RTT,而且还频繁的调用系统 IO,发送网络请求。为了提升效率,pipeline 出现了,它允许客户端可以一次发送多条命令,而不等待上一条命令执行的结果。
=====实现思路=====
客户端首先将执行的命令写入到缓冲区中,最后再一次性发送 Redis。但是有一种情况就是,缓冲区的大小是有限制的:如果命令数据太大,可能会有多次发送的过程,但是仍不会处理 Redis 的应答。
=====实现原理=====
要支持 pipeline,既要服务端的支持,也要客户端支持。对于服务端来说,所需要的是能够处理一个客户端通过同一个 TCP 连接发来的多个命令。可以理解为,这里将多个命令切分,和处理单个命令一样。对于客户端,则是要将多个命令缓存起来,缓冲区满了就发送,然后再写缓冲,最后才处理 Redis 的应答。
=====Redis pipeline 的参考资料=====
https://redis.io/topics/pipelining
=====在php中使用Redis pipeline=====
=====总结:Redis pipeline 的特性以及使用时需要注意的地方=====
pipeline 减少了 RTT,也减少了IO调用次数(IO 调用涉及到用户态到内核态之间的切换)
如果某一次需要执行大量的命令,不能放到一个 pipeline 中执行。数据量过多,网络传输延迟会增加,且会消耗 Redis 大量的内存。应该将大量的命令切分为多个 pipeline 分别执行。
Redis 的工作过程是基于 请求/响应 模式的。正常情况下,客户端发送一个命令,等待 Redis 应答;Redis 接收到命令,处理后应答。请求发出到响应的时间叫做往返时间,即 RTT(Round Time Trip)。在这种情况下,如果需要执行大量的命令,就需要等待上一条命令应答后再执行。这中间不仅仅多了许多次 RTT,而且还频繁的调用系统 IO,发送网络请求。为了提升效率,pipeline 出现了,它允许客户端可以一次发送多条命令,而不等待上一条命令执行的结果。
=====实现思路=====
客户端首先将执行的命令写入到缓冲区中,最后再一次性发送 Redis。但是有一种情况就是,缓冲区的大小是有限制的:如果命令数据太大,可能会有多次发送的过程,但是仍不会处理 Redis 的应答。
=====实现原理=====
要支持 pipeline,既要服务端的支持,也要客户端支持。对于服务端来说,所需要的是能够处理一个客户端通过同一个 TCP 连接发来的多个命令。可以理解为,这里将多个命令切分,和处理单个命令一样。对于客户端,则是要将多个命令缓存起来,缓冲区满了就发送,然后再写缓冲,最后才处理 Redis 的应答。
=====Redis pipeline 的参考资料=====
https://redis.io/topics/pipelining
=====在php中使用Redis pipeline=====
<?php //实例化redis $redis = new Redis(); //连接 $redis->connect('127.0.0.1', 6379); $redis->pipeline();//开启管道 if(!$redis){ throw new Exception('redis连接失败!',1); } $key = "pipeline_test"; $len = 200000; $succ = 0; for($i=0;$i<$len;$i++){ $res = $redis->hset($key,"test_".$i,1); if($res){ $succ ++; } } $redis->exec();
=====总结:Redis pipeline 的特性以及使用时需要注意的地方=====
pipeline 减少了 RTT,也减少了IO调用次数(IO 调用涉及到用户态到内核态之间的切换)
如果某一次需要执行大量的命令,不能放到一个 pipeline 中执行。数据量过多,网络传输延迟会增加,且会消耗 Redis 大量的内存。应该将大量的命令切分为多个 pipeline 分别执行。
常用正则表达式总结
标签:
正则
一、校验数字的表达式
1 数字:^[0-9]*$ 2 n位的数字:^\d{n}$ 3 至少n位的数字:^\d{n,}$ 4 m-n位的数字:^\d{m,n}$ 5 零和非零开头的数字:^(0|[1-9][0-9]*)$ 6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 7 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 8 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$ 9 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$ 10 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$ 11 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ 12 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ 13 非负整数:^\d+$ 或 ^[1-9]\d*|0$ 14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ 15 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 16 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 17 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ 18 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ 19 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
二、校验字符的表达式
1 汉字:^[\u4e00-\u9fa5]{0,}$ 2 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ 3 长度为3-20的所有字符:^.{3,20}$ 4 由26个英文字母组成的字符串:^[A-Za-z]+$ 5 由26个大写英文字母组成的字符串:^[A-Z]+$ 6 由26个小写英文字母组成的字符串:^[a-z]+$ 7 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 8 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$ 9 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$ 10 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ 11 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+ 12 禁止输入含有~的字符:[^~\x22]+
三、特殊需求表达式
1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ 2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? 3 InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ 4 手机号码:^(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])\d{8}$ (由于工信部放号段不定时,所以建议使用泛解析 ^([1][3,4,5,6,7,8,9])\d{9}$) 5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7} 7 18位身份证号码(数字、字母x结尾):^((\d{18})|([0-9x]{18})|([0-9X]{18}))$ 8 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 9 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$ 10 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 11 日期格式:^\d{4}-\d{1,2}-\d{1,2} 12 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$ 13 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$ 14 钱的输入格式: 15 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$ 16 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$ 17 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$ 18 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$ 19 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$ 20 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$ 21 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 22 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ 23 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里 24 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$ 25 中文字符的正则表达式:[\u4e00-\u9fa5] 26 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) 27 空白行的正则表达式:\n\s*\r (可以用来删除空白行) 28 HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力) 29 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) 30 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始) 31 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字) 32 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用) 33 IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))
php简单工厂、工厂模式、抽象工厂实例总结
简单工厂
<?php /** * Created by PhpStorm. * User: xingdong * Date: 2019/8/3 * Time: 上午10:05 */ //简单工厂 interface Product { public function getPrice(); public function getName(); } class ProductA implements Product { public function getPrice() { return 100; } public function getName() { return 'ProductA'; } } class ProductB implements Product { public function getPrice() { return 200; } public function getName() { return 'ProductB'; } } class ProductC implements Product { public function getPrice() { return 300; } public function getName() { return 'ProductC'; } } class Factory { public static function createProduct($type) { $product = null; switch ($type){ case "A": $product = new ProductA(); break; case "B": $product = new ProductB(); break; case "C": $product = new ProductC(); break; } return $product; } } $productA = Factory::createProduct('A'); $productB = Factory::createProduct('B'); $productC = Factory::createProduct('C'); /** * 以上便是简单工厂模式的一个典型事例,当用户需要新增产品ProductD时,必须在工厂类的生产方法中增加 对应的判断分支,所以简单工厂模式违背了开放封闭原则。 简单工厂模式,利用静态方法根据输入参数生成对应的产品,隐藏了产品实例化的细节。 总结: 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类, 对于客户端来说,去除了与具体产品的依赖。但是当需求变动的时候,需要对原有的类进行修改,违背了开放封闭原则。 * * */工厂模式
<?php /** * Created by PhpStorm. * User: xingdong * Date: 2019/8/3 * Time: 上午10:05 */ //工厂方式模式 interface Product { public function getPrice(); public function getName(); } class ProductA implements Product { public function getPrice() { return 100; } public function getName() { return 'ProductA'; } } class ProductB implements Product { public function getPrice() { return 200; } public function getName() { return 'ProductB'; } } class ProductC implements Product { public function getPrice() { return 300; } public function getName() { return 'ProductC'; } } interface IFactory{ public function createProduct(); } class FactoryA implements IFactory { public function createProduct() { return new ProductA(); } } class FactoryB implements IFactory { public function createProduct() { return new ProductB(); } } class FactoryC implements IFactory { public function createProduct() { return new ProductC(); } } $factoryA = new FactoryA(); $factoryA->createProduct(); $factoryB = new FactoryB(); $factoryB->createProduct(); $factoryC = new FactoryC(); $factoryC->createProduct(); /** * 当需要增加一个新产品ProductD,只需要新建对应的FactoryD来实现生产功能即可,对原有的代码 没有任何影响,非常符合开放封闭原则,但是由于每增加一个产品,都需要新增对应的生产工厂,导致增加额外的开发工作量。 总结:由于使用了多态,工厂方法克服了简单工厂违背的开放封闭原则的缺点,又保持了封装对象创建过程的优点。 */抽象工厂
<?php /** * Created by PhpStorm. * User: xingdong * Date: 2019/8/3 * Time: 上午10:05 */ //抽象工厂方式 //商品 interface Product { public function getPrice(); public function getName(); } class ProductA implements Product { public function getPrice() { return 100; } public function getName() { return 'ProductA'; } } class ProductB implements Product { public function getPrice() { return 200; } public function getName() { return 'ProductB'; } } class ProductC implements Product { public function getPrice() { return 300; } public function getName() { return 'ProductC'; } } //礼品 interface Gift { public function getGiftName(); } class GiftA implements Gift { public function getGiftName() { return 'GiftA'; } } class GiftB implements Gift { public function getGiftName() { return 'GiftB'; } } class GiftC implements Gift { public function getGiftName() { return 'GiftC'; } } interface IFactory{ public function createProduct(); public function createGift(); } class FactoryA implements IFactory { public function createProduct() { return new ProductA(); } public function createGift() { return new GiftA(); } } class FactoryB implements IFactory { public function createProduct() { return new ProductB(); } public function createGift() { return new GiftB(); } } class FactoryC implements IFactory { public function createProduct() { return new ProductC(); } public function createGift() { return new GiftC(); } } $factoryA = new FactoryA(); $factoryA->createProduct(); $factoryB = new FactoryB(); $factoryB->createProduct(); $factoryC = new FactoryC(); $factoryC->createProduct(); /** * 总结:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。 抽象工厂接口,应该包含所有的产品创建的抽象方法,我们可以定义实现不止一个接口, 一个工厂也可以生产不止一种产品类,和工厂方法模式一样,抽象工厂模式同样实现了开发封闭原则 */
数据结构之数组和链表
====数组=====
1.在内存中,数组是一块连续的区域
2.数组需要预留空间,在使用前需要提前申请所占内存的大小
3.在数组起始位置处,插入数据和删除数据效率低
-插入数据时,待插入位置的元素和它后面的所有元素都需要向后搬移
-删除数据时,待删除位置后面的所有元素都要向前搬移
4.随机访问速度效率很高,时间复杂度可以到达O(1)
因为数组的内存是连续的,想要访问那个元素,直接从数组的首地址向后偏移就可以访问到了
5.数组开辟的空间,在不够使用的时候需要扩容,扩容的话,就会涉及需要把旧数组的所有数据向新数组中搬移
6.数组的空间是从栈分配的
====数组的优点====
随机访问性强,查找速度快,时间复杂度O(1)
====数组的缺点====
1.头插和头删的效率低,时间复杂度O(N)
2.空间利用率不高
3.内存空间要求高,必须有足够的连续的内存空间
4.数组空间的大小固定,不能动态扩展
=====链表=====
1.在内存中,元素的空间可以在任意地方,空间是分散的,不需要连续
2.链表中的元素都会两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址
每一个数据都会保存下一个数据的内存的地址,通过此地址可以找到下一个数据
3.查找数据时效率低,时间复杂度为O(N)
因为链表的空间是分散的,所以不具有随机访问性,如要需要访问某个位置的数据,需要从第一个数据开始找起,依次往后遍历,直到找到待查询的位置,故可能在查找某个元素时,时间复杂度达到O(N)
4.空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高
5.任意位置插入元素和删除元素效率较高,时间复杂度为O(1)
6.链表的空间是从堆中分配的
====链表的优点====
1.任意位置插入元素和删除元素的速度快,时间复杂度为O(1)
2.内存利用率高,不会浪费内存
3.链表的空间大小不固定,可以动态拓展
====链表的缺点====
随机访问效率低,时间复杂度为0(N)
1.在内存中,数组是一块连续的区域
2.数组需要预留空间,在使用前需要提前申请所占内存的大小
3.在数组起始位置处,插入数据和删除数据效率低
-插入数据时,待插入位置的元素和它后面的所有元素都需要向后搬移
-删除数据时,待删除位置后面的所有元素都要向前搬移
4.随机访问速度效率很高,时间复杂度可以到达O(1)
因为数组的内存是连续的,想要访问那个元素,直接从数组的首地址向后偏移就可以访问到了
5.数组开辟的空间,在不够使用的时候需要扩容,扩容的话,就会涉及需要把旧数组的所有数据向新数组中搬移
6.数组的空间是从栈分配的
====数组的优点====
随机访问性强,查找速度快,时间复杂度O(1)
====数组的缺点====
1.头插和头删的效率低,时间复杂度O(N)
2.空间利用率不高
3.内存空间要求高,必须有足够的连续的内存空间
4.数组空间的大小固定,不能动态扩展
=====链表=====
1.在内存中,元素的空间可以在任意地方,空间是分散的,不需要连续
2.链表中的元素都会两个属性,一个是元素的值,另一个是指针,此指针标记了下一个元素的地址
每一个数据都会保存下一个数据的内存的地址,通过此地址可以找到下一个数据
3.查找数据时效率低,时间复杂度为O(N)
因为链表的空间是分散的,所以不具有随机访问性,如要需要访问某个位置的数据,需要从第一个数据开始找起,依次往后遍历,直到找到待查询的位置,故可能在查找某个元素时,时间复杂度达到O(N)
4.空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高
5.任意位置插入元素和删除元素效率较高,时间复杂度为O(1)
6.链表的空间是从堆中分配的
====链表的优点====
1.任意位置插入元素和删除元素的速度快,时间复杂度为O(1)
2.内存利用率高,不会浪费内存
3.链表的空间大小不固定,可以动态拓展
====链表的缺点====
随机访问效率低,时间复杂度为0(N)