PageRank算法
来源:互联网 发布:php 通过接口查询数据 编辑:程序博客网 时间:2024/05/02 02:56
总算有一个周末下午时间,决定亲手把pagerank算法实现一下。 之前只是看过思路,并一直使用同事的实现版本。
关于PageRank的介绍,请看
http://zh.wikipedia.org/wiki/PageRank
http://baike.baidu.com/view/1518.htm
不多废话了,直接进入正题,C++实现。
公式采用:
PR(A) = (1-d) +d(PR(t1)/C(t1) + ... + PR(tn)/C(tn))
样例,采用 http://zh.wikipedia.org/wiki/PageRank 中介绍的 A, B, C, D 四个站点,另外图采用邻接表存储方式(不是邻接矩阵,可根据习惯调整)
详情请看:http://www.webworkshop.net/pagerank.html
代码实现:C++语言: 贴彩色代码可用:http://fayaa.com/code/new/
为了方便构建图,使用了STL的数据结构,希望不会造成阅读障碍。
PageRank.h:
#include <set>
#include <string>
#include <iostream>
using namespace std;
// use graph store webpage, weight representlink times
class Node
{
public:
explicit Node(string name, double pr = 1):name_(name), page_rank_(pr){}
~Node()
{
linkin_nodes_.clear();
}
void InsertLinkdInNode(Node* node)
{
//如果没有链接
if (linkin_nodes_.find(node) == linkin_nodes_.end())
{
linkin_nodes_.insert(node);
}
node->InsertLinkOutNode(this);
}
void InsertLinkOutNode(Node* node)
{
//如果没有链接
if (linkout_nodes_.find(node) == linkout_nodes_.end())
{
linkout_nodes_.insert(node);
}
}
double GetPageRank()
{
return page_rank_;
}
void SetPageRank(double pr)
{
page_rank_ = pr;
}
double CalcRank()
{
double pr = 0;
set<Node*>::const_iterator citr = linkin_nodes_.begin();
for (; citr != linkin_nodes_.end(); ++citr)
{
Node * node = *citr;
pr += node->GetPageRank()/node->GetOutBoundNum();
}
return pr;
}
size_t GetOutBoundNum()
{
return linkout_nodes_.size();
}
size_t GetInBoundNum()
{
return linkin_nodes_.size();
}
void PrintNode()
{
cout << "Node:" << name_ << " 's pagerank is: " << page_rank_ << endl;
}
private:
string name_;
set<Node*> linkin_nodes_;
set<Node*> linkout_nodes_;
double page_rank_;
};
class PageRank
{
public:
PageRank(double q=0.85);
~PageRank(void);
void Calc(vector<Node*> & nodes, int n);
double Calc(Node* node);
void PrintPageRank(vector<Node*> & nodes);
private:
double q_; //阻尼系数
};
PageRank.cpp
#include <iostream>
PageRank::PageRank(double q) : q_(q)
{
// q_ must < 1
}
PageRank::~PageRank(void)
{
}
// 迭代计算n次
void PageRank::Calc(vector<Node*> & nodes, int n)
{
for (int i=0; i<n; ++i)
{
vector<Node*>::const_iterator citr = nodes.begin();
for (; citr!=nodes.end(); ++citr)
{
Node * node = *citr;
Calc(node);
}
}
}
void PageRank::PrintPageRank(vector<Node*> & nodes)
{
double total_pr = 0;
vector<Node*>::const_iterator citr = nodes.begin();
for (; citr!=nodes.end(); ++citr)
{
Node * node = *citr;
node->PrintNode();
total_pr += node->GetPageRank();
}
cout << "Total PR:" << total_pr << endl;
}
double PageRank::Calc(Node * node)
{
double pr = node->CalcRank();
if (pr < 0.00000000000000000000001 && pr > -0.00000000000000000000001) //pr == 0
{
pr = 1-q_;
}
else
{
pr = pr * q_ + 1-q_;
}
node->SetPageRank(pr);
return pr;
}
main.cpp
#include <vector>
#include <string>
#include <map>
#include "PageRank.h"
using namespace std;
void InitGraph(vector<Node*> & nodes)
{// 邻接表存储方式
// example 1
Node * a = new Node("A");
Node * b = new Node("B");
Node * c = new Node("C");
Node * d = new Node("D");
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
nodes.push_back(d);
// link in node
// a <- b, c, d
a->InsertLinkdInNode(b);
a->InsertLinkdInNode(c);
a->InsertLinkdInNode(d);
// b <- d
b->InsertLinkdInNode(d);
// c <- b, d
c->InsertLinkdInNode(b);
c->InsertLinkdInNode(d);
}
void TestPageRank()
{
// build graph
vector<Node*> nodes;
InitGraph(nodes);
PageRank pr;
// 迭代计算5次 pagerank
pr.Calc(nodes, 40);
pr.PrintPageRank(nodes);
}
int main(int argc, const char ** argv)
{
TestPageRank();
return 0;
}
运行结果验证: http://www.webworkshop.net/pagerank_calculator.php?lnks=9,11,17,25,26,27&ilnks=&iblprs=&pgnms=&pgs=4&initpr=1&its=40&type=simple
截图:下面两个结果为初始pr值1,迭代计算40次后的结果对比,完全吻合。
这里只实现了simple mode,对于real mode等进一步探索,感兴趣的读者按实际需求进一步研究吧。
希望对于不熟练编程实现的人,能起到入门参考作用。
- PageRank算法
- PageRank算法
- PageRank 算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- PageRank算法
- pagerank算法
- PageRank算法
- PageRank算法
- PageRank 算法
- PageRank算法
- mysql分析工具
- 李彦宏:黑马是怎样炼成的
- Page cache和buffer cache的区别与联系(ZT)
- NSOperationQueue线程队列完毕finished状态检测
- Android之路-生命周期
- PageRank算法
- 程序员们 不要想一辈子靠技术混饭吃
- 关于oracle with table as的用法
- 落户csdn
- 网络编程之小小示例
- 电子工程师的百变人生(上)
- 电子工程师的百变人生(下)
- 子衿的事(58)
- 外企面试--基本涵盖了所有问题(很长)