最近自己在寫網站,用的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;//這裏返回的就是推薦關注的用戶標識啦
}
上述純屬自己瞎想了寫的。。代碼很醜陋,但是最終還是能實現,哈哈。