第7章 神奇的树

简介: 第7章 神奇的树

第7章 神奇的树

第1节 开启“树”之旅

不含回路的连通无向图。

现实中的族谱、操作系统中的“目录”。

树的相关概念:略略略

第2节 二叉树

二叉树是每个节点最多有两个儿子的树。

满二叉树、完全二叉树(满二叉树的一部分)

完全二叉树存储规律:只要用一个一维数组就可以存储完全二叉树,将完全二叉树进行从上到下,从左到右编号,,可以发现如果父节点的编号是k,那么它的子节点的编号是2k和2k+1。若子节点是x,父节点就是x/2。

第3节 堆–神奇的优先队列

堆是一种特殊的完全二叉树,所有的父节点比子节点小。称为最小堆。如果所有的父节点比子节点大,则称为最大堆。

最小堆的操作:

void siftdown(int i) { //从i向下调整(i插入一个数后)
    int flag = 0;
    int t;
    while(i*2<=n && flag==0) {
      if(h[i]>h[i*2]) {
        t = i*2;
      }else {
        t=i;
      }
      if(i*2+1 <= n) {
        if(h[t]>h[i*2+1]) {
          t = i*2+1;
        }
      }
      if(t!=i) {
        int k = h[t];
        h[t] = h[i];
        h[i] = k;
        i = t;
      }else {
        flag = 1;
      }
    }
  }

向上调整(插入末尾)

  void siftup(int i) {//从i向上调整
    int flag = 0;
    if(i==1) return;
    while(i!=1 && flag==0) {
      if(h[i]<h[i/2]) {
        int kk = h[i];
        h[i] = h[i/2];
        h[i/2]=kk;
      }else {
        flag = 1;
      }
      i = i/2;
    }
  }

建立堆

  //建立堆
  void create() {
    for(int i=n/2;i>=1;i--) {
      siftdown(i);
    }
  }


完整的对排序:

package ch7;

import java.util.Scanner;

public class Test1 {

  int[] h = new int[101];
  int n;
  void siftdown(int i) { //从i向下调整
    int flag = 0;
    int t;
    while(i*2<=n && flag==0) {
      if(h[i]>h[i*2]) {
        t = i*2;
      }else {
        t=i;
      }
      if(i*2+1 <= n) {
        if(h[t]>h[i*2+1]) {
          t = i*2+1;
        }
      }
      if(t!=i) {
        int k = h[t];
        h[t] = h[i];
        h[i] = k;
        i = t;
      }else {
        flag = 1;
      }
    }
  }
  
  void siftup(int i) {//从i向上调整
    int flag = 0;
    if(i==1) return;
    while(i!=1 && flag==0) {
      if(h[i]<h[i/2]) {
        int kk = h[i];
        h[i] = h[i/2];
        h[i/2]=kk;
      }else {
        flag = 1;
      }
      i = i/2;
    }
  }
  
  
  //建立堆
  void create() {
    for(int i=n/2;i>=1;i--) {
      siftdown(i);
    }
  }

  
  //堆排序,每次删除顶部元素
  int deletetop() {
    int t;
    t = h[1];
    h[1] = h[n];
    n--;
    siftdown(1);
    return t;
  }
  
  
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int num = sc.nextInt();
    Test1 t1 = new Test1();
    for(int i=1;i<=num;i++) {
      t1.h[i] = sc.nextInt();
    }
    t1.n = num;
    t1.create();
    for(int i=1;i<=num;i++) {
      System.out.print(t1.deletetop()+ " ");
    }
  } 
}

另一种堆排序的方法:建立最大堆,h[1]是最大的数,每次把h[1]和h[n]交换,h[n]就是最大的数,然后n–,在从h[1]向下调整。直到堆只剩下一个数。(最大堆和最小堆类似,只是最大堆的父结点大于子节点)

void heapsort(){
  while(n>1){
    swap(1,n);
    n--;
    siftdown(1);//
  }
}

第4节 擒贼先擒王–并查集

有n个强盗,m条线索,每条线索给出的是x号强盗和y号强盗是同伙,求一共有多少个犯罪团伙。

//测试数据
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
//结果3
package ch7;

import java.util.Scanner;

public class Test2 {
  int[] f = new int[1000];
  int n,m,k,sum;
  //初始化f
  void init() {
    for(int i=1;i<=n;i++) {
      f[i] = i;
    }
  }
  //找爹的递归函数
  int getf(int v) {
    if(f[v]==v) {
      return v;
    }else {
      f[v] = getf(f[v]);//路径压缩,每次函数返回时,顺便将遇到的人的Boss改为最后找到的祖宗编号
      return f[v];
    }
  }
  //合并子集(同伙)
  void merge(int v,int u) {
    int t1 = getf(v);
    int t2 = getf(u);
    if(t1 != t2) {
      f[t2] = t1; //靠左原则,合并到左边
    }
  }
  
  public static void main(String[] args) {
    
    Scanner sc = new Scanner(System.in);
    Test2 t2 = new Test2();
    t2.n = sc.nextInt();
    t2.init();

    int m = sc.nextInt();
    for(int i=1;i<=m;i++) {
      int x = sc.nextInt();
      int y = sc.nextInt();
      t2.merge(x, y);
    }
    
    for(int i=1;i<=t2.n;i++) {
      if(t2.f[i]==i) {
        t2.sum++;
      }
    }
    System.out.println(t2.sum);
    
  }
}

相关文章
|
5月前
|
存储 算法 Unix
简单介绍一些其他的树
简单介绍一些其他的树
|
存储 缓存 关系型数据库
B树与B+树
B树与B+树
43 0
B树与B+树
|
存储 缓存 算法
B树,B-树,B+树和B*树
B树,B-树,B+树和B*树
|
存储 关系型数据库 MySQL
B树和B+树的理解
B树和B+树的理解
B树和B+树的理解
|
存储
你说什么是树?
你说什么是树?
107 0
你说什么是树?
|
存储
心里有点树 (一)
心里有点树 (一)
193 0
|
存储
心里有点树 (三)
心里有点树 (三)
142 0
|
Java 容器
心里有点树 (二)
心里有点树 (二)
105 0
|
存储 数据库 索引
B树和B+树
本文转载自博客,因为题主写的已经很详细了。 还有,必须要强调一点,树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下,只有减少树的深度,让树从“高瘦”变成“矮胖”就可以减少I/O次数,从而提高查询效率(查找树的每一个结点都要进行一次I/O) B树是为实现高效的磁盘存取而设计的多叉平衡搜索树。
2095 0