php三种常用的排序算法

 更新时间:2016年11月25日 15:51  点击:1646

php教程三种常用的排序算法

1、冒泡排序(稳定排序)

个人理解:冒泡排序就是两个循环,大循环套小循环,从头或者尾部开始比较连续的两个元素的大小,如果不符合自己的排序标准(由小到大,或由大到小),则交换其值。

<?php
$arr=array(10,15,16,18,20,3,9,7,18,99);
for($i=1;$i<=9;$i++)
   for($j=1;$j<=10-$i;$j++)
      if($arr[$j-1]>$arr[$j])
      {$temp=$arr[$j-1];$arr[$j-1]=$arr[$j];$arr[$j]=$temp;}
      echo"after sorted:";
   for($i=0;$i<=9;$i++)
      echo $arr[$i].",";
     
 ?>

方法二

function bubble_sort($array){

  $count=count($array);

  for($i=0;$i<$count;$i++){

    for($j=$count-1;$j>$i;$j--){

      if($array[$j]<$array[$j-1]){//如果后面的值小于前面的元素,则交换值

        $temp=$array[$j];

        $array[$j]=$array[$j-1];

        $array[$j-1]=$temp;

      }

    }

  }

}

2、快速排序(又称数组排序)(不稳定排序)

个人理解:在要排序的数组中找一个关键数据(标准值),通常把数组的第一个元素当成关键数据,然后循环数组,从第二个元素开始依次将元素值与关键数据进行比较,如果小于关键数据,就把该元素放在关键值左边,如果答应关键数据,就把该元素放在关键数据右边,将关键值左边元素存成数组,右边元素也存成数组,再分别进行以上排序,得到的数组与关键数据合并数组后就排序成功

function quick_sort($array){

  $count=count($array);

  if($count<=1) retrun $array;  //如果数组只有一个元素或为空,则直接返回数组,不用排序了

  $key=$array[0]; //将数组第一个元素设置为关键数据

  $left_arr=array();

  $right_ar=array();

  for($i=1;$i<$count;$i++){

    if($array[$i]<=$key)

      $left_arr[]=$array[$i];

    else

      $right_arr[]=$array[$i];

  }

  $left_arr=quick_sort($left_arr);

  $right_arr=quick_sort($right_arr);

  //返回合并后的数组

  return array_merge($left_arr,array($key),$right_arr);

}

3、选择排序(不稳定排序)

个人理解:选择排序就是在要排序的数组中选出最小值与第一个元素交换值,然后再剩下的元素中选出最小值与第二个元素交换值,如此循环到倒数第二个元素和最后一个元素比较为止。

function select_sort($array){

  $count=count($array);

  if($count<=1) return $array;

  for($i=0;$i<$count-1;$i++){

    $min=$array[$i]; //假设当前元素为数最小,比较后再调整

    for($j=$i+1;$j<$count;$j++){

      if($array[$j]<$min){

        $min=$array[$j];

        $key=$j; //将此时值最小的元素的键名记下,

      }

    }

    if($min!=$array[$i]){ //如果min在循环中改变了,就需要交换数据

      $temp=$array[$i];

      $array[$i]=$array[$key];

      $array[$key]=$temp;

    }

  }

}

 

当然使用 Session 还有很多优点,比如控制容易,可以按照用户自定义存储等(存储于数据库教程)。我这里就不多说了。

  Session 在 php教程.ini 是否需要设置呢?一般不需要的,因为并不是每个人都有修改 php.ini 的权限,默认 Session 的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍。

  开始介绍如何创建 Session。非常简单,真的。

  启动 Session 会话,并创建一个 $admin 变量:

// 启动 Session
session_start();
// 声明一个名为 admin 的变量,并赋空值。
$_SESSION["admin"] = null;
?>

  如果你使用了 Seesion,或者该 PHP 文件要调用 Session 变量,那么就必须在调用 Session 之前启动它,使用 session_start() 函数。其它都不需要你设置了,PHP 自动完成 Session 文件的创建。

  执行完这个程序后,我们可以到系统临时文件夹找到这个 Session 文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是 32 位编码后的随机字符串

,函数bool session_set_save_handler ( callback open, callback close, callback read, callback write, callback destroy, callback gc )就是提供给我们解决这个问题的方案.
该函数使用的6个函数如下:
1. bool open() 用来打开会话存储机制,
2. bool close() 关闭会话存储操作.
3. mixde read() 从存储中装在session数据时使用这个函数
4. bool write() 将给定session ID的所有数据写到存储中
5. bool destroy() 破坏与指定的会话ID相关联的数据
6. bool gc() 对存储系统中的数据进行垃圾收集
例子见php手册session_set_save_handler() 函数.
如果用类来处理,用

 

session_set_save_handler(
array('className','open'),
array('className','close'),
array('className','read'),
array('className','write'),
array('className','destroy'),
array('className','gc'),
)

关于session安全问题
攻击者通过投入很大的精力尝试获得现有用户的有效会话ID,有了会话id,他们就有可能能够在系统中拥有与此用户相同的能力.
http协议时无状态的,所以通常网站都会用session来标示一个用户。session在客户端就是一个保存一个特殊令牌的cookie,关键的信息是存放在服务器端的。但因为令牌是保存在客户端,并且要经过传输,所以还是很不安全的。

1、会话终止,但令牌仍处于活动状态

情景: 当用户退出时,程序只是删除了令牌(例如,通过发布一个清空令牌的Set-Cookie指令)。然而并没有删除服务器端的数据,如果用户继续使用该令牌,仍然可以使用。
解决方法:退出后删除服务器端的数据。
测试方法:退出后,仍然使用该令牌,如果活动正常,这该令牌仍然有效。(使用Firefox的web developer 插件就可以)

2、令牌可以通过url传输

情景:如果可以通过url传输,攻击者使用攻击者站点上的链接,可以轻松的固定受害人的会话标识符,比如:http://www.example.com/index.php?PHPSESSID=fixed_session_id。假使受害者还没有一个example.com站点会话标识符的cookie,那么会话固定就成功了。一旦受害者使用了攻击者指定的会话标识符,那么攻击者就能劫持受害者的会话,并模仿受害者的用户代理,试图假装成受害者。
解决方法:在PHP中设置 use_only_cookies  的值 1 , 在php中默认就是 1,可以不修改。

3、在网络上泄露了令牌

情景:网络以非加密方式传输会话令牌,则处在适当位置的监听者可以截取此令牌。
a、当用户登录时是使用http非安全通道时,用户与服务器间传输的所有的数据都是可以截获的。 这时登录者对于监听者是没有什么秘密可言的。这时候,如果截获的数据不足以执行第二次登录  (例如,一些银行系统会要求登录者提交不断变化的验证码)。如果攻击者想执行任何操作,就必须劫持他窃听的会话。

b、一些程序在一些HTTP页面就发送一个令牌,然后再登录页面开始使用https教程,并且登录时也不修改此令牌,结果最初并未通过验证的用户会话在登录后被升级为通过验证的会话。窃听者可以在登录前就拦截到这个令牌。所以为了提高安全性,程序可以在登录的时候发送令牌或发送一个新令牌。

c、程序容许通过HTTP登录,如果攻击者成功将用户的链接降级为HTTP,他仍然能够拦截这个令牌。

d、如果所有的页面都是用HTTPS,但图片和一些js,css教程等的静态文件是使用HTTP传输。这时如果静态文件和登录等页面时在同一个域下,令牌也会通过HTTP泄露。所以将静态文件使用别的域好处是很多的。
其他解决方法:
a、如果应用程序使用HTTP Cookie传送会话令牌,应确认其设置了secure标记,防止他们通过非加密链接传送令牌。
b、不接受非安全登录
c、session和客户端的HTTP_USER_AGENT绑定,但该方法效果不是很理想,攻击者可以伪造这些数据。

4、客户端令牌易被劫持

a、网站存在跨站攻击漏洞,这样用户的令牌很容易被劫持。需要检查全站,避免出现跨站攻击,也可以设置cookie_httponly,可以在一定程度上避免脚本的攻击。具体可以参考  利用httponly提升应用程序安全性 

b、攻击者可以使用其他针对用户的攻击,以不同的方式劫持用户的会话。包括实施会话固定攻击,即攻击者向一名用户发送一个已知的会话令牌,等待他们登录。
解决方法:1、可以每次登录成功后发送新的会话令牌
2、对令牌设定一个特别的格式,不接受其他格式的令牌,该方法效果并不是很好。


5、Cookie范围过于宽泛

浏览器在提交Cookie时会将Cookie提交到设定的域及其任何子域,而不提交到其他域。如果应用程序将Cookie的域设定的过于宽泛,会是程序出现各种漏洞。


6、令牌不够强大


令牌在其生成过程中,过于简单,或者有规律可循,从而使攻击者可以以常规方式预测或推断其他用户的令牌。例如,攻击者可以在A时间得到从网站正常获取一个令牌,在B时间在网站获取一个令牌,则通过分析,得到这个时间段的大量令牌样本,从而攻击。


解决方法:生成一个强大的令牌,得到足够的复杂度。但一些高强度的随机源必须采用足够的步骤获得足够的熵,这需要时间,所以通常不能满足需求。所以可以通过合并一些用户特有的数据来得到足够的熵。可以使用的数据:
1、一串随机数
2、来源IP地址
3、请求中的User_Agent消息头
4、请求时间
5、服务器私密的随机数
串联上面的数据,然后使用适当的散列算法(比如md5,SHA-256)等等对这个字符串处理。(将最容易变化的数据项放在散列输入的开始部分有助于最大化散列算法中的“雪崩”效应。


其他的一些增强安全的方法:

1、每页面令牌
在每个页面使用新的令牌,可以通过HTML表单传送,也可以使用Cookie传送,如果出现不匹配的情况整个会话终止。

2、在执行重要操作前,要求进行两步确认操作

安全是个大问题,细节方面是最重要的。这篇文章是我在阅读《黑客攻防技术宝典-web实战篇》记下的笔记。
--冷锋

<?php
if(!isset($_SESSION['user_agent'])){
$_SESSION['user_agent'] =$_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];
}
/* 如果用户session ID是伪造 */
elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] .$_SERVER['HTTP_USER_AGENT']) {
session_regenerate_id();
}
?>

今天使用POST方式(GET方式也要注意)向PHP提交了一个JSON数据,比如:

{"a":1,"b":2}

在PHP中取出这个数据:

$s=$_POST['data'] ;//or $_GET['data']

然后这个串取出后是被转义的:

 {"a":1,"b":2}

如果直接调用:

$obj = json_decode($s); 

print_r($obj); 
echo $obj->a;
 是错误的,会报告错误.

如果$s直接定义:

$s='{"a":1,"b":2}';

则没有问题.

所以在PHP中处理JSON时需要进行一下转义处理:

$s=strips教程lashes($_POST['data']) ;

这样再进行json解码就可以了.


json_decode — 对 JSON 格式的字符串进行编码
json_encode — 对变量进行 JSON 编码

Report a bug 说明
string json_encode ( mixed $value )
返回 value 值的 JSON 形式

Report a bug 参数

value
待编码的 value ,除了resource 类型之外,可以为任何数据类型

该函数只能接受 UTF-8 编码的数据(译注:指字符/字符串类型的数据)


Report a bug 返回值
编码成功则返回一个以 JSON 形式表示的 string 。

Report a bug 范例

Example #1 A json_encode() 的例子

<?php教程
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);

echo json_encode($arr);
?>
以上例程会输出:

{"a":1,"b":2,"c":3,"d":4,"e":5}

 

json_encode — 对变量进行 JSON 编码

json_decode — 对 JSON 格式的字符串进行编码

Report a bug 说明
mixed json_decode ( string $json [, bool $assoc ] )
接受一个 JSON 格式的字符串并且把它转换为 PHP 变量

Report a bug 参数

json
待解码的 json string 格式的字符串。

assoc
当该参数为 TRUE 时,将返回 array 而非 object 。


Report a bug 返回值
Returns an object or if the optional assoc parameter is TRUE, an associative array is instead returned.

Report a bug 范例

Example #1 json_decode() 的例子

<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

var_dump(json_decode($json));
var_dump(json_decode($json, true));

?>
以上例程会输出:

object(stdClass)#1 (5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

array(5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

 

位运算符

 位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。

 在 32 位系统上不要右移超过 32 位。不要在结果可能超过 32 位的情况下左移。

  例子                  名称                               结果
 $a & $b     And(按位与)    将把 $a 和 $b 中都为 1 的位设为 1。
 $a | $b      Or(按位或)      将把 $a 或者 $b 中为 1 的位设为 1。
 $a ^ $b     Xor(按位异或)    将把 $a 和 $b 中不同的位设为 1。
 ~ $a      Not(按位非)    将 $a 中为 0 的位设为 1,反之亦然。
 $a << $b   Shift left(左移)    将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
 $a >> $b   Shift right(右移)    将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。

<?php教程

$a=1; 
$b=1;
echo "<br/>And(按位与)";    //将把 $a 和 $b 中都为 1 的位设为 1
echo $a&$b;      //显示值  1

echo "<br/>Or(按位或)";    //将把 $a 或者 $b 中为 1 的位设为 1
echo $a|$b;      //显示值  1

echo "<br/> Xor(按位异或)";//将把 $a 和 $b 中不同的位设为 1
echo $a^$b;      //显示值  0

echo "<br/>Not(按位非)";    //将 $a 中为 0 的位设为 1,反之亦然
echo ~$a;      //显示值  -2

echo "<br>Shift left(左移)";//将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)
echo $a<<$b;      //显示值  2

echo "<br/>Shift right(右移)";//将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
echo $a>>$b;       //显示值 0

?>

位运算符允许对整型数中指定的位进行置位。如果左右参数都是字符串,则位运算符将操作字符的 ASCII 值。


<?php
echo 12 ^ 9; // 输出为 '5'

echo "12" ^ "9"; // 输出退格字符(ascii 8)
                    // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // 输出 ascii 值 #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4

echo 2 ^ "3"; // 输出 1
              // 2 ^ ((int)"3") == 1

echo "2" ^ 3; // 输出 1
              // ((int)"2") ^ 3 == 1                           
?>

PHP Session 变量

<?php教程
    session_start ();
    $music = "A";
    session_register ('music');

    echo $music;
?>
    

当您运行一个应用程序时,您会打开它,做些更改,然后关闭它。这很像一次会话。计算机清楚你是谁。它知道你何时启动应用程序,并在何时终止。但是在因特网上,存在一个问题:服务器不知道你是谁以及你做什么,这是由于 HTTP 地址不能维持状态。

通过在服务器上存储用户信息以便随后使用,PHP session 解决了这个问题(比如用户名称、购买商品等)。不过,会话信息是临时的,在用户离开网站后将被删除。如果您需要永久储存信息,可以把数据存储在数据库教程中。

Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,亦或通过 URL 进行传导。
开始 PHP Session
在您把用户信息存储到 PHP session 中之前,首先必须启动会话。

注释:session_start() 函数必须位于 <html> 标签之前:

<?php session_start(); ?>

<html>
<body>

</body>
</html>上面的代码会向服务器注册用户的会话,以便您可以开始保存用户信息,同时会为用户会话分配一个 UID。
存储 Session 变量
存储和取回 session 变量的正确方法是使用 PHP $_SESSION 变量:

<?php
session_start();
// store session data
$_SESSION['views']=1;
?>

<html>
<body>

<?php
//retrieve session data
echo "Pageviews=". $_SESSION['views'];
?>

</body>


</html>输出:

Pageviews=1在下面的例子中,我们创建了一个简单的 page-view 计数器。isset() 函数检测是否已设置 "views" 变量。如果已设置 "views" 变量,我们累加计数器。如果 "views" 不存在,则我们创建 "views" 变量,并把它设置为 1:

<?php
session_start();

if(isset($_SESSION['views']))
  $_SESSION['views']=$_SESSION['views']+1;

else
  $_SESSION['views']=1;
echo "Views=". $_SESSION['views'];


php session_start()关于Cannot send session cache limiter - headers
解决办法:
修改php.ini中的session.auto_start = 0 为 session.auto_start = 1
output_buffering =改为on或者任何数字。
然后别忘记重新启动...


错误提示
Warning: Cannot send session cookie - headers already sent
Warning: Cannot send session cache limiter - headers already sent
分析及解决办法
这一类问题,的原因是你在程序中使用PHP session_start()时,之前已经有实际的html内容输出了。或许你说,我没有啊,我只不过是echo或print一条消息了。很抱歉,你的echo或print语句所产生的输出,就是实际的html内容输出。解决此类问题的办法是,将你的session_start()调到程序的第一行。


Warning: Trying to destroy uninitialized session in
分析及解决方法
出类这样的提示,一般情况都是你直接调session_destroy()函数造成的。很多的朋友认为session_destroy()函数可以独立的运行,其实不然。解决的方法是在你调session_destroy()函数之前,要用PHP session_start()开启session的功能。

[!--infotagslink--]

相关文章

  • C#几种排序算法

    作者:Sabine 【导读】本文介绍了C#的四种排序算法:冒泡排序、选择排序、插入排序和希尔排序  冒泡排序 using System; namespace BubbleSorter { public class Bubb...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • antdesign-vue结合sortablejs实现两个table相互拖拽排序功能

    这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-09
  • C# 参数按照ASCII码从小到大排序(字典序)

    这篇文章主要介绍了C# 参数按照ASCII码从小到大排序(字典序)的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • js实现列表按字母排序

    这篇文章主要为大家详细介绍了js实现列表按字母排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-11
  • C#实现排序的代码详解

    在本篇文章里小编给大家整理的是关于C#实现排序的代码以及相关知识点,需要的朋友们参考下。...2020-06-25
  • C#中实现任意List的全组合算法代码

    这篇文章主要是介绍了.net C# 实现任意List的全组合算法实现代码,需要的朋友可以参考下...2020-06-25
  • 同时兼容JS和C#的RSA加密解密算法详解(对web提交的数据加密传输)

    这篇文章主要给大家介绍了关于同时兼容JS和C#的RSA加密解密算法,通过该算法可以对web提交的数据进行加密传输,文中通过图文及示例代码介绍的非常详细,需要的朋友们可以参考借鉴,下面来一起看看吧。...2020-06-25
  • 图文详解Heap Sort堆排序算法及JavaScript的代码实现

    这篇文章以图文详解Heap Sort堆排序算法及JavaScript的代码实现,堆排序算法基于类二叉树的堆数据结构,需要的朋友可以参考下...2016-05-05
  • js实现数组冒泡排序、快速排序原理

    这篇文章主要为大家详细介绍了js实现数组冒泡排序、快速排序的原理,感兴趣的小伙伴们可以参考一下...2016-03-10
  • c# n个数排序实现代码

    c# n个数排序实现代...2020-06-25
  • 分享javascript实现的冒泡排序代码并优化

    本文给大家汇总介绍了几个个人收藏的JavaScript实现冒泡排序的代码,都是非常的不错,有需要的小伙伴可以参考下...2016-06-12
  • C#常用数据结构和算法总结

    这篇文章主要介绍了C#常用数据结构和算法,这里我们总结了一些知识点,可以帮助大家理解这些概念。...2020-06-25
  • C#使用linq对数组进行筛选排序的方法

    这篇文章主要介绍了C#使用linq对数组进行筛选排序的方法,实例分析了C#实用linq扩展进行数组排序的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • JS实现的随机排序功能算法示例

    这篇文章主要介绍了JS实现的随机排序功能算法,结合具体实例形式分析了javascript常用的排序算法实现技巧,需要的朋友可以参考下...2017-06-15
  • C#实现冒泡排序算法的代码示例

    冒泡排序即是对数组每次轮循出最大数或最小数放在队尾,这里我们来看一下C#实现冒泡排序算法的代码示例,需要的朋友可以参考下...2020-06-25
  • c# 实现位图算法(BitMap)

    这篇文章主要介绍了c# 如何实现位图算法(BitMap),文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-11-03
  • C++实现的O(n)复杂度内查找第K大数算法示例

    这篇文章主要介绍了C++实现的O(n)复杂度内查找第K大数算法,结合实例形式分析了算法的原理以及具体实现方法,需要的朋友可以参考下...2020-04-25
  • 一篇文章带你搞懂Vue虚拟Dom与diff算法

    这篇文章主要给大家介绍了关于Vue虚拟Dom与diff算法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-08-26
  • R语言关于随机森林算法的知识点详解

    在本篇文章里小编给大家整理的是一篇关于R语言关于随机森林算法的知识点详解内容,有兴趣的朋友们可以跟着学习下。...2021-05-13