最近自己在写网站,用的thinkphp3.2,水了两年才开始接触除开课设和写题以外的东西。
网站里写了关注和粉丝之类的东西。然后想到微博有推荐关注这么一回事。虽然不知道微博是什么思路实现的,也不知道实现的原理。但想到平时写题遇到的分类的问题都是用并查集来解决的。
首先要实现粉丝关注的功能。下面是实现这个关系数据库里的表。
数据库表:
create table tp2_follow(
foid int not null auto_increment primary key, //关注号,主码
followmyid int, //如果有个关系是我关注你,那么followmyid就是我的用户标识
followyouid int, //followyouid顾名思义就是关注对象的用户标识
followflag int default 0 //默认0,表示未关注,1表示关注,主要是为了取消关注后变更为0。
) default charset=utf8;
实现粉丝关注后,先想一想推荐关注的实现:
如果当前登录的用户是1,那么从数据库中查找与用户1相关的并且用户1未关注的人,这些人就是需要推荐给用户1关注的。
与用户1相关的并且用户1未关注的人,这么解释吧,现在有关系:1关注2,2关注3,2关注4,那么1、2、3、4就是一个集合,他们都互相是有关系的,是一个朋友圈。但是1没有关注3、4,于是将3、4推荐给1关注。
这种算谁和谁是一个集合的问题,就需要利用并查集了。并查集用c语言实现的话,主要是2个函数,一个find,一个mid,具体实现的思路这里就不多说了,贴一下c的代码:
find函数:
int find(int x){//查找祖先节点
if(pre[x] != x)pre[x] = find(x);
return pre[x];
}
mix函数:
void mix(int x, int y){//合并2个节点
int fx = find(x), int fy = find(y);
if(fx != fy) pre[fx] = fy;
}
那么thinkphp只需要仿照着c的思路写就ok了:
php的find函数:
public function bcjfind(&$pre = array(), $x)
{
if($pre[$x] != $x)
{
$pre[$x] = $this->bcjfind($pre, $pre[$x]);
}
return $pre[$x];
}
php的mix函数:
public function bcjmix(&$pre = array(), $x, $y)
{
$fx = $this->bcjfind($pre, $x);
$fy = $this->bcjfind($pre, $y);
if($fx != $fy)
{
$pre[$fx] = $fy;
}
}
实现这个功能的函数:
public function recommend()
{
$id = $_SESSION["uid"];//登录这个用户的用户标识
$allusernum = D("user")->queryfoundmaxid();//对数据库的操作,查找到用户标识中最大的标识,也就是有多少个用户
for($row=1; $row<=$allusernum; $row++)//并查集的初始化,让所有节点的祖先等于他自己
{
$pre[$row] = $row;
}
$allfollowdata = D("user")->foundallfollowdata();//把所有关注关系成立的数据查出来,也就是followflag为1的关系数据
for($row=0; $row<count($allfollowdata); $row++)
{
$this->bcjmix($pre, $allfollowdata[$row]["followmyid"], $allfollowdata[$row]["followyouid"]);//用并查集把相关的人合为一个集合
}
$i = 0;
$tmp = $this->bcjfind($pre, $id);//查找登录用户标识的祖先
for($row=1; $row<=$allusernum; $row++)//从小到大把所有用户标识遍历一遍,只要是和登录者用户标识祖先相同的就给存下来
{
if($row != $_SESSION["uid"] && $pre[$row] == $tmp && D("user")->checkmenotfollowyou($_SESSION["uid"], $row))
{
$data[$i++]["id"] = $row;
}
}
$go = array();
for($row=0; $row < 3; $row++)//这个循环其实可以不用要,我主要是为了每次随机推荐三个人,控制推荐人数的。
{
if($row < count($data))
{
$flag = 1;
while($flag)
{
$tt = $data[rand()%count($data)]["id"];
$flag = 0;
for($r = 0; $r < $row; $r++)
{
if($go[$r]["id"] == $tt)
{
$flag = 1;
}
}
$go[$row]["id"] = $tt;
}
}
}
return $go;//这里返回的就是推荐关注的用户标识啦
}
上述纯属自己瞎想了写的。。代码很丑陋,但是最终还是能实现,哈哈。