排序练习第一弹–插入排序

排序算法的种类是多种多样,各有各的长处,这几天会一一进行分析。学习应该有一个先后递进的过程,从容易的开始。

先说比较简单的 — 插入排序(由PHP代码实现,这里不讲究效率!)

 

[php]

/**
* 插入排序 — 比冒泡稍微复杂一点的排序算法 *
*
**/

$array = array(‘5′,’6′,’3′,’1′,’2′,’4’);

/**
* 插入排序1 — 使用最暴力的排序
*
**/

function insertSort($array)
{
$count = count($array); //先取出一个数据最为比较数据
for($i=1;$i<$count;$i++)
{
$key = $array[$i];
$j = $i-1;
while($j>=0 && $array[$j]>$key)
{
$array[$j+1] = $array[$j];
$j = $j-1;
$array[$j+1] = $key;
}
var_dump($array);
}
}

insertSort($array);
[/php]

下面是运行结果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

嗯,整个算法已经完了!如果你只想要代码的。你事情已经完成了,下面开始讲原理。

插入排序之所以叫插入排序,我们可以形象的理解为:

你摸牌的时候,你手里的牌是有序的,而你从牌堆里摸的牌是随机出现的,你只需跟你手里的牌进行比较排序,就能确定新牌的位置

插入的排序的逻辑可以简单的理解为,从第二个元素前,开始跟第一个元素进行比较,如果比对一个元素小,该元素就插入到第一个元素的前面

如果大,则跟第二个元素进行比较,以此类推。(从效果图中,可以看出来)

再来看看插入排序的时间发杂度:

  1. 最优的情况,所有的N-1个元素只需要跟前面的元素比较一次,那么时间复杂度是n-1;
  2. 最差的勤快,所有的N-1个元素都需要跟前面的所有元素比较一次,那么时间复杂度是一个等差数列 ((n-1)*(n-2))/2+(n-1);

综上所述:插入排序的时间复杂度应该是位于这两则之间。

空间复杂度: 插入排序是一种线性排序。所有空间复杂度跟参与排序的N有关。

PHP程序登录搜狐广告获取广告联盟数据

一直有一个想法,每次都要登录去看联盟昨天收益多少?每天都要登录和麻烦,能不能做一个汇总发邮件的功能呢?

可惜了,验证码绕不过去,只能想一个办法。先在服务器手动打一次验证码,然后在通过定时器,每隔10分钟请求一个页面

这样的话Cookies就不会失效,,然后每周只需要跟我汇总数据就Ok了。。

远程提交表单的原理,可以参考:PHP后台远程登录正方教务系统

参考的代码还是一样的如下

获取验证码Code.php

[php]
define("SITE_PATH", $_SERVER[‘DOCUMENT_ROOT’]);
$LoginUrl = "http://union.sogou.com/";
$url = $LoginUrl."validateCode";
$filedir = SITE_PATH."/TMP/Cookies";
$cookie_file = $filedir."/cookie.txt";

if(!mkdirs($filedir))
{
  echo "目录创建失败";
   exit;
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0); //不返回header部分
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
//curl_setopt($ch, CURLOPT_REFERER, "http://125.89.69.234");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, "10");

$response = curl_exec($ch);
curl_close($ch);
header("Content-type:image/gif");
echo $response;

//创建目录
function mkdirs($dir)
{
     if(!is_dir($dir))
{
if(!mkdirs(dirname($dir))){
return false;
}
if(!mkdir($dir,0777)){
return false;
}
}
return true;
}
[/php]

获取数据的页面,这里需要通过表单来提交手动的验证码

[php]

define("SITE_PATH", $_SERVER[‘DOCUMENT_ROOT’]);
require_once SITE_PATH.’/class/SimpleHtmlDom.class.php’;
class GetData{

private $url ;

public function __construct(){

$this->url = "http://union.sogou.com/index.action?searchBean.timeSegment=yestoday";
$this->LoginUrl = "http://union.sogou.com/";
$this->PostData = $this->LoginUrl."loginauth.action";
$this->table = "dwz_union";

}

public function post($code)
{
$POST[‘loginFromPage’] = "homePage";
$POST[‘username’] = "xxxxxx";
$POST[‘password’] = "xxxxx";
$POST[‘activecode’] = $code;
$POST[‘button.x’]="14";
$POST[‘button.y’]="16";

foreach($POST as $key=>$value)
{
$tmp[] = $key."=".$value;
}

$postStr = implode("&", $tmp);

$filedir = SITE_PATH."/TMP/Cookies";
$cookie_file = $filedir."/cookie.txt";

$result = $this->curl($this->PostData, "http://union.sogou.com/loginauth.action", $postStr, $cookie_file);

$url = "http://union.sogou.com/index.action";

$postArr = "searchBean.timeSegment=yestoday";

$response = $this->curl($url, " http://union.sogou.com/index.action?pid=dengwz7788", $postArr, $cookie_file);

$this->saveData($response);
}

private function saveData($response)
{

$dom = str_get_html($response);

$tmp = $dom->find(‘div.rtable table tbody tr’,1)->plaintext;

$data = preg_split("/\s+/i", $tmp);

$this->link();

$date = date(‘Y-m-d’,strtotime(‘-1 day’));
$datetime = date(‘Y-m-d H:i:s’);
$money = $data[‘4’];
$shows = $data[‘2’];
$times = $data[‘3’];

$sql = "select sum(money) as total from {$this->table}";

$query = mysql_query($sql);

$totaTmp = mysql_fetch_row($query);

var_dump($totalTmp);

if(empty($totaTmp[‘0’]))
{
$total = $money;
}else{
$total = $totaTmp[‘0’]+$money;
}

$sql = "insert into {$this->table}(date,datetime,money,shows,times,total) values(‘{$date}’,'{$datetime}’,'{$money}’,'{$shows}’,'{$times}’,'{$total}’)";

mysql_query($sql);
}

private function link()
{
$link = mysql_connect(‘localhost’, ‘root’, ”);
mysql_select_db(‘dblog’, $link);
mysql_query(‘SET NAMES utf8’);
}

private function saveHtml($infomation,$filedir,$filename)
{

if(!$this->mkdirs($filedir))
{
return 0;
}

$sf = $filedir."/".$filename;
$fp=fopen($sf,"w"); //写方式打开文件
fwrite($fp,$infomation); //存入内容
fclose($fp); //关闭文件
}

//创建目录
private function mkdirs($dir)
{
if(!is_dir($dir))
{
if(!$this->mkdirs(dirname($dir))){
return false;
}
if(!mkdir($dir,0777)){
return false;
}
}
return true;
}

public function login()
{

$filedir = SITE_PATH."/TMP/Cookies";

if(!$this->mkdirs($filedir))
{
echo "目录创建失败";
exit;
}

$cookie_file = $filedir."/cookie.txt";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->LoginUrl);
curl_setopt($ch, CURLOPT_HEADER, 0); //不返回header部分
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
//curl_setopt($ch, CURLOPT_REFERER, "http://125.89.69.234");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, "10");

$response = curl_exec($ch);

curl_close($ch);

// 鍏抽棴CURL浼氳瘽

}

private function curl($url,$url2,$fields,$cookie_file)
{

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0); //不返回header部分
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: union.sogou.com" ));
curl_setopt($ch, CURLOPT_REFERER,$url2);

$response = curl_exec($ch);

//echo curl_error($ch);
curl_close($ch);
return $response;
}

}

$GetData = new GetData();

if(isset($_POST[‘code’]))
{
$GetData->POST($_POST[‘code’]);

}

[/php]

PHP代码下载

Centos环境下安装SVN服务器并且理解“高端的打分支”技术

发版策略:分支开发,主干发版


分支开发的意义:
场景一,有客户想对产品做定制,但是我们并不想修改原有的svn中trunk的代码。
场景二,我们正在开发产品下阶段的任务,但上阶段的工作发现问题
以场景二为例,项目某一阶段开发完成后,这个时候要做一个tag,tag_mfcai_V1.01.00,
然后基于这个tag发布一个新的版本,假设项目是web项目,那么基于这个tag发布一个web包。
然后trunk进入下阶段继续开发,但是很不幸发布的版本被检测出来了bug,有人会提议,把bug放到下阶段的任务中去。假设下阶段的任务才刚开始,用户可等不起.他们会认为一个小的bug解决要这么长时间,效率太低了.
那么就需要基于tag_mfcai_V1.01.00做一个branch,branch_bugfix_V1.01.00,基于这个branch进行bugfix,
等到bugfix结束,做一个tag,tag名称假设为:tag_mfcai_V1.01.01,基于这个tag再发布一个版本。
这样,又没有影响trunk(主分支)的开发。然后,根据需要决定branch_bugfix_V1.01.00是否并入trunk。
如何使用先进的分支技术

  • “小乌龟”操作(图文并茂)

 

再介绍点打tag的知识。确认项目组成员的代码都commit后。

1)右击要打tag的目录—>TortoiseSVN—>branch/tag

2)再弹出来的对话框中,要求输入分支或标记的目标路径

3)创建分支或标记的时候,你有三个选项版本库中的最新版本,版本库中的指定版本,工作副本。

开始打分支第一步

1:指分支将存在的目录

2:分支的注释(不能丢呀,等分支多了!就搞坨数不清楚的拉)

3:这里分别说明三个分别是说明啥意思

     1)Head revision in the repository  –直接从版本库中最新创建,由于不需要从你的工作拷贝中传输数据,创建过程会很快。

     2)  Specific revision in repository   ——同样是从版本库中创建,不同的是你可以指定一个版本号。如果你忘了版本号,可以通过显示版本记录来找到你想要的版本号(如下图)。这种方式同样不需要从你的工作拷贝中传输数据,创建过程也很快。

     3)  Woking copy ——这种方式会依据当前工作拷贝的版本状况(无论是你做了本地的修改,或是将其中的某些文件更新到了一个历史版本)来创建分支拷贝。这种创建方式会根据工作副本中每个文件的版本情况来决定是否要从工作拷贝向版本库中传输数据。

在这里我们必需先弄明白一个合并背后的关健概念

合并的过程中发生的所有事:首先两个版本库树的比较,然后将区别应用到本地拷贝.

这个命令是包括三个参数的:

  1. 初始的版本树 2.最终的版本树 3一个接收区别的工作拷贝。 

弄明白这些概念之后我们继续往下操作。

在弹出的窗口中,选择主线目录和其版本号(初始的版本树),再选择主线目录和最新的版本号(最终的版本树),这里也可以是某一个版本号但应该比初始的版本树的版本号要高,接收区默认为你右键所指的目录,这里是clientt。

在合并之前我们可以通过点击“Unified diff”,查看两版本树之间所有文件的内容的变化,“diff”显示出有发生变化的文件列表,“dry run”能显示真正合并时的状态信息,但并没有做任何的合并操作。

我们点击“Merge”。
这里选择的是合并两个不同的版本树
分支合并到主线跟从主线上合并内容到分支上类似 
不同的是
1、开始的版本库是分支创建的版本

2、结束的版本库是完成所以开发工作之后的版本

3、应用的目的是主线目录
SVN服务器代建小礼包
SVN 关闭服务器 killall svnserve
SVN 开启服务器 svnserve -d -r  /SVN目录
后面的代建的全过程
系统环境
RHEL5.4最小化安装(关iptables,关selinux) + ssh + yum
一,安装必须的软件包.
yum install subversion (SVN服务器)
mysql-server (用于codestriker)

二,基本的SVN服务器配置
1,新建一个目录用于存储SVN所有文件
# mkdir /home/svn
2,新建一个版本仓库
# svnadmin create /home/svn/project
3,初始化版本仓库中的目录
# mkdir project project/server project/client project/test (建立临时目录)
# svn import project/ file:///home/svn/project -m “初始化SVN目录”

SVN服务器代建之后一定要初始化,不然根本就用不了。
4,添加用户

要添加SVN用户非常简单,只需在/home/svn/project/conf/passwd文件添加一个形如“username=password”的条目就可以了.为了测试,我添加了如下内容:

[html]
[users]
# harry = harryssecret
# sally = sallyssecret
Admin=admin
[/html]

5,修改用户访问策略
/home/svn/project/conf/authz记录用户的访问策略,以下是参考:

[html]
[/]
Admin=rw
Admin 所有的目录都是读写的权限
[/html]

6,修改svnserve.conf文件,让用户和策略配置升效.
svnserve.conf内容如下:

[html]
[general]
anon-access = none
auth-access = write
password-db = /home/svn/project/conf/passwd
authz-db = /home/svn/project/conf/authz
[/html]

7,启动服务器

[html]
# svnserve -d -r /home/svn
[/html]

8,测试服务器

[html]
# svn co svn://192.168.60.10/project
Authentication realm: &lt;svn://192.168.60.10:3690&gt; 92731041-2dae-4c23-97fd-9e1ed7f0d18d
Password for ‘root’:
Authentication realm: &lt;svn://192.168.60.10:3690&gt; 92731041-2dae-4c23-97fd-9e1ed7f0d18d
Username: Admin
Password for ‘admin’:
svn: Authorization failed ( server_group没用根目录的访问权 )
A    project/test
A    project/server
A    project/client
Checked out revision 1.  ( 测试提取成功 )
# cd project/server
# vim main.c
# svn add main.c
# svn commit main.c -m "测试一下我的C程序,看什么看,不行啊??"
Adding         main.c
Transmitting file data .
Committed revision 2.  ( 测试提交成功 )
[/html]

如果你代建的SVN服务器都OK,但是小乌龟无法访问:防火墙的问题。。。简单粗暴的方法: etc/ini.d/iptables stop
当然不是好太建议直接关闭防火墙:(SVN默认是3690端口)

[html]
RH-Firewall-1-INPUT -p tcp -m state –state NEW -m tcp –dport 3690 -j ACCEPT
[/html]

再送一个小礼包
[html][/html]
SVN Error: Unreadable path encountered; access denied;
[html][/html]
解决方法:
编辑[代码仓库目录下]/conf/svnserve.conf
将[anon-access]的值设置为[none]
记得重启SVN服务器

我的PM理解

  做过一段技术了,虽然没有参与到整个产品从立项到上线的全过程,一般都作为一个编码施工方参与到其中的一个环节。但我对PM这个职位还是有我自己的理解方式。如果有不正确的地方,还望指正。
     需求调研阶段(企业软件,不同于互联网产品)
  1.  跟需求方第一次交流,算是了解需求的大概功能点。
  2.  整理需求方功能点,做出功能分析。可以用多种(PPT,思维导图)方式跟需求再次沟通,这算是需求确立
  3.  完成原型图(最理想的方式是直接做出正品效果图),然后跟需求方确认样式,排版和交互细节问题。
  4.  交予施工方(包括前端,后端)功能的实现。
  5.  验收阶段,PM当然是验收第三人(第一人是施工人员,第二人是施工方测试人员)。
  6.  交予需求方
    上述的这个流程是一个十分理想和很健康的流程,可惜实现总是充满了故事性。
    比如:
  1.  需求确定以后,需求方中途要加功能怎么办?
  2.  效果页面已经确定,需求方像改样式,这么办?
   个人理解的PM职责:
        他需要良好的理解人能和表达能力,能过对需求方的需求做出开速的反应和功能的理解。
        最好有一点的技术基础和实际项目的经验。懂技术的PM才是好的设计师。

如何获取用户在点击广告联盟的真实数据

我一直想做一个统计广告点击的功能。(因为我做的那个博客活动需要这个功能)

说干就干,在自己的页面做了一个统计功能来查看!有多少人点的了我的广告。

起初的想法是:JS绑定区域,获取鼠标的位置,如果用户在该区域click了。那么就算一次点击(但算不算有效点击,有待考证)

广告联盟

广告联盟

针对上图这个400px*60px图,找到红点位置的坐标就可以获取该广告区域的4点的坐标。然后再通过这四个点。

来确定鼠标的X,Y是否在该区域内。

有了这个思想做指导,用jquery代码实现就相当简单了。

[javascript]

$(".ad_bannar").one("mouseover",function(e) {
var pointX = e.pageX; //这里可得到鼠标X坐标
var pointY = e.pageY;//这里可以得到鼠标Y坐标
var xstar = ‘124’;
var xend = ‘584’;
var ystar = ‘376’;
var yend = ‘436’;

if(pointX>=xstar &&pointX<=xend && pointY>=ystar && pointY<=yend) {

$.post("./getData.php",{type:’tongguan’},function(){
console.log(‘+1’);
})
}
});
[/javascript]

PS:但还是有一个JS很“头大”的问题。我用ONE()函数绑定的时候用的是mouseover而不是click.这样用户有没有点击,你还是不知道。因为你用click的时候,你其实是点击的另一个页面而不是你绑定的函数的功能页面。

求网友的智慧帮忙解决。。。。。

又到一年校招时

时间过的真快,还记得去年这个时候,还在为工作奔波,到处投简历找工作!转眼间又到一年校招时。

入职已经快四个月了。前几月一直在适应新环境,然后就开始做公司校招收简历模块了。

说实话,第一次看到校招投递简历的数据,真把我吓到了!(初生牛犊不怕虎,为了去年捏把汗)

4399校招简历投递页面

4399校招简历投递页面

这个页面是我们设计部设计的,感觉还是很清新自然的,我就负责的PHP端和前端JS特效。 继续阅读

一道PHP笔试题(进阶必备)

上次,一个前辈发了一道PHP笔试给我,题目大致如下

[php]

$arr = array(‘1′,’2′,’3’);

foreach($arr as $key=>&$val){}

foreach($arr as $key=>$val){}

var_dump($arr);

[/php]

问答案是什么?

看完我就懵了?根本不知道问题的考点在那里,看完两个foreach的区别在一个是取了地址,一个没有取地址,,这样会影响结果吗?

结果输出的结果居然是

[php]
array(
0 => string ‘1’ (length=1)
1 => string ‘2’ (length=1)
2 => &string ‘2’ (length=1)
)
[/php]

继续阅读

PHP小偷程序的设计与实现

其实自己一直想做一个内涵图片的网站,以前的想法是做一个CMS,然后自己上传一些图片。。

开始真这么做的,没什么动力。之后就放弃了,后来研究了一个CURL。反正还是把这个想法实现比较好。

用PHP盗图,就好比:穿着袜子穿凉鞋一样。虽然没问题,但看着确实蛋疼

我先说一下我对PHP小偷程序的设计,PHP不支持多线程,这样就只能分先后顺序来做了

获取到目标网站的HTML页面+解析HTML页面获取到图片存储的连接+用二进制方式读取并且保存在本地+重命名  == 流程OK

你现在用两种方式来运行程序:

第一种:用游览器跑程序(多半会卡死,设置超时和内存大小就OK,你之间比较难等) 继续阅读

Jquery插件Z-tree

最近做一个树型的目录,由于本人JS学的太烂了,在网上找了一个jQuery插件–ztree

看官网都感动我哭了,这完整的解决方案,作者这急人之所急。

给一个连接  ztree官网

你们去看一下就知道了,Mark一下不会有错的。

 

PHP流 — 被PHPer遗忘的一些关键

本文完全是因为对PHP流的兴趣造成的,早在做微信公共账号的时候,发现微信接口返回的数据,不管是用POST还是用GET或者是REQUEST都接收不到。

才发现原来,在这些底层还有一种数据传输,二进制流。

用$GLOBALS[“HTTP_RAW_POST_DATA”]或者 file_get_contents(‘php://input’)。

     这跟POST有什么区别?

从官方的手册来看

The RAW / uninterpreted HTTP POST information can be accessed with:

$GLOBALS[‘HTTP_RAW_POST_DATA’] This is useful in cases where the post Content-Type is not something PHP understands (such as text/xml)

也就是说,基本上$GLOBALS[‘HTTP_RAW_POST_DATA’] 和 $_POST是一样的。但是如果post过来的数据不是PHP能够识别的,你可以

用 $GLOBALS[‘HTTP_RAW_POST_DATA’]来接收,比如 text/xml 或者 soap 等等。

PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型

用Content-Type=text/xml 类型,你就不能用POST获取了

继续阅读