C++ Basic Data Structure Part3

basic data structure and algorithm part2

图论

图的实现

  • V为点的个数 E边的个数
  • 邻接矩阵
    • 用一个n*n的矩阵
      • 第一列第二个为1的意思是
        • 第一个点和第二个点相连
        • 1为权值
    • O(V2)
    • 用一个二维数组实现
  • 邻接表
    • 用一个n长度的数组
      • 然后每一个数组后面接的链表里面存着
        • 这个数组index对应的点和哪些点相连
          • 这些点存在链表里面
    • O(V+E)
    • stl实现
    • 用vector list
      • 然后Node就是每个点
        • 如果有别的点和这个Node相连,就list.push_back(别的点)

图搜索

广度优先搜索
  • 使用的数据结构是queue
  • 相当于先把第一层的所有点入队
    • 然后把每个点的相邻的节点入队
      • e.g
        • 假设第一层的节点为A, 第二层为B,第三层为C
          • 那么队列中的情况就是
            • A,B,C,A1,A2,A3,B1,C2
            • 这样访问下来,就相当于一层一层的遍历了
  • 伪代码
1
2
3
4
5
6
7
8
9
10
11
12
13
function bfs(vertex v){
  create a queue Q
  enqueue v into Q
  mark v as visited
  while Q is not empty{
      use temp to store Q.top
      dequeue the top vertex from Q
      for each adjacent w in temp{
          mark w as visited
          enqueue w into Q
      }
  }
}
深度优先搜索
  • 使用的数据结构是stack
  • 伪代码
1
2
3
4
5
6
7
8
function dfs(vertex v){
  mark v as visited //把点标记为已经访问过了
  for each node adjacent to v //对这个点的所有邻接点进行搜索
      if node is unvisited  //如果从左到右,找到这个点没有被访问过
          dfs(node) //递归调用
      //如果这个点访问过了
          //那么向右移,继续搜索
}
二叉树的BFS和DFS
  • 首先递归建树
    • 再用bfs和dfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define Element char
typedef struct Node{
  Element data;
  struct Node *left;
  struct Node *right;
}*Tree;
int i = 0;
//按照先序遍历建树
void construct_tree(Tree &root, Element data[]){
  Element e = data[i++];
  if(e == '#')
      root = NULL;
  else{
      root = new Node();
      root -> data = e;
      construct_tree(root -> left, data); //递归建立左子树
      construct_tree(root -> right, data); //递归建立右子树
  }   
}
void bfs(Tree root){  
  queue<Node *> q;
  q.push(root);
  while(!q.empty()){
      Node *temp = q.front();
      q.pop();
      cout<<temp -> data;
      if(temp -> left)
          q.push(temp -> left);
      if(temp -> right)
          q.push(temp -> right);
  }
}
void dfs(Tree root){
  stack<Node *> s;
  s.push(root);
  while(!s.empty()){
      Node *temp = s.top();
      s.pop();
      cout<<temp -> data;
      //因为stack是先进后出,所以先把right压进去
      if(temp -> right)
          s.push(temp -> right);
      if(temp -> left)
          s.push(temp -> left);
  }
}
int main(){
  //#表示没有左子树或者右子树
  //             A
  //           /   \
  //          B     C
  //        /  \   /  \
  //      D    E   F   G
  Element data[15] = {'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#'};
  Tree tree;
  construct_tree(tree, data);
  //bfs
  cout<<"result of bfs: ";
  bfs(tree);
  cout<<endl;
  //dfs
  cout<<"result of dfs: ";
  dfs(tree);
  cout<<endl;
  return 0;
}
拓扑排序
  • 方法
    • 用在有向图里面
    • 选择一个入度为0的点,输出
      • 然后删除这个点和所有和他相连的出去的边

最短路径

  • 单源最短路
  • Dijkstra算法
    • 首先把起点加入集合
    • 每次查询的时候
      • 把和这个集合最近的那个点加入集合
      • 然后递归
  • floyd算法
    • 原理是动态规划
    • 首先得出图的邻接矩阵
      • 然后如果i==j那么为0,因为自己到自己的距离为0
      • 如果两个点不邻接,那么为INF(很大的数字)
    • 其次,如果有N个点,那么就要对矩阵进行n次更新
      • 依次把距离当前集合距离最小的点加入集合
      • 并且更新矩阵数据
      • 如果a[i][j] > a[i][k] + a[k][j]
        • 则a[i][j] = a[i][k] + a[k][j]
    • 最后得出的矩阵就是包含所有点到所有点的最短距离

最小生成树(todo)

  • Prim
  • Kruskal
Comments

Comments