《啊哈!算法》第七章

双更撒花~是不是很勤快!(我才不会说是因为我的大会员到期了才空出时间写代码了嘿嘿嘿)
在这里插入图片描述
7.1 ?的概念
树的特性:
1、一棵树中的任意两个结点有且仅有唯一的一条路径连通。
2、一棵树如果有n个结点,那么它一定恰好有n-1条边。
3、在一棵树中加一条边将会构成一条回路。
深度:根到该结点的层数(根是第一层)

7.2 二叉树?的概念
满二叉树:二叉树中每个内部结点都有两个儿子,即满二叉树的所有的叶结点都有同样的深度
完全二叉树:除了最后一排结点缺失若干个,前面符合满二叉树要求的树。
如果一个父结点编号为k,则它的左孩子编号为2k,右孩子编号为2k+1。如果孩子的编号为x,则它的父结点编号为x/2。
如果一个完全二叉树(不包括满二叉树)有N个结点,则它的高度为logN+1。

7.3 堆
7.3.1 向下调整

import java.util.Scanner;

class Test{
    static int n;
    static int[] heap=new int[100];
    public void swap(int i,int j){
        int tmp;
        tmp=heap[i];
        heap[i]=heap[j];
        heap[j]=tmp;
    }
    public void shiftdown(int i){
        int min;
        int flag=0;
        while(i*2<=n&&flag==0){
            if(heap[i]>heap[2*i])
                min=2*i;
            else
                min=i;
            if(i*2+1<=n) {
                if (heap[min] > heap[2 * i + 1])
                    min=2*i+1;
            }
            if(min!=i) {
                swap(i, min);
                i = min;
            }
            else
                flag=1;
        }
    }
    public static void main(String[] args){
        Test t=new Test();
        System.out.println("请输入结点数量");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        System.out.println("请输入结点");
        for(int i=1;i<=n;i++)
            heap[i]=sc.nextInt();
        for(int i=n/2;i>=1;i--)
            t.shiftdown(i);
        for(int i=1;i<=n;i++)
            System.out.print(heap[i]+" ");
    }
}

7.3.2 向上调整。它的复杂度为什么是O(n),小啾想了一种解释,不知道对不对,复杂度O<n/21+n/42+n/83+n/164…最后是一个k*n的形式,可推断其复杂度为n级。好像有点不严谨…看着玩儿好啦。

import java.util.Scanner;

class Test{
    static int n;
    static int[] heap=new int[100];
    public void swap(int i,int j){
        int tmp;
        tmp=heap[i];
        heap[i]=heap[j];
        heap[j]=tmp;
    }
    public void shiftup(int i){
        int flag=0;
        if(i==1) return;
        while(i!=1&&flag==0){
            if(heap[i]<heap[i/2])
                swap(i,i/2);
            else flag=1;
            i=i/2;
        }
    }
    
    public static void main(String[] args){
        Test t=new Test();
        System.out.println("请输入结点数量");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        System.out.println("请输入结点");
        for(int i=1;i<=n;i++)
            heap[i]=sc.nextInt();
        for(int i=n;i>=1;i--)
            t.shiftup(i);
        for(int i=1;i<=n;i++)
            System.out.print(heap[i]+" ");
    }
}

7.3.3 堆排序-最小堆

import java.util.Scanner;

class Test{
    static int n;
    static int[] heap=new int[100];
    public void swap(int i,int j){
        int tmp;
        tmp=heap[i];
        heap[i]=heap[j];
        heap[j]=tmp;
    }
    public void shiftdown(int i){
        int min;
        int flag=0;
        while(i*2<=n&&flag==0){
            if(heap[i]>heap[2*i])
                min=2*i;
            else
                min=i;
            if(i*2+1<=n) {
                if (heap[min] > heap[2 * i + 1])
                    min=2*i+1;
            }
            if(min!=i) {
                swap(i, min);
                i = min;
            }
            else
                flag=1;
        }
    }
    public int deletetop(){
        int tmp=heap[1];
        heap[1]=heap[n];
        n--;
        shiftdown(1);
        return tmp;
    }
    public static void main(String[] args){
        Test t=new Test();
        System.out.println("请输入结点数量");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        System.out.println("请输入结点");
        for(int i=1;i<=n;i++)
            heap[i]=sc.nextInt();
        for(int i=n/2;i>=1;i--)
            t.shiftdown(i);
        int total=n;
        for(int i=1;i<=total;i++)
            System.out.print(t.deletetop()+" ");
    }
}
/*
99 5 36 7 22 17 46 12 2 19 25 28 1 92
 */

7.3.4 堆排序-最大堆

import java.util.Scanner;

class Test{
    static int n;
    static int[] heap=new int[100];
    public void swap(int i,int j){
        int tmp;
        tmp=heap[i];
        heap[i]=heap[j];
        heap[j]=tmp;
    }
    public void shiftdown(int i){
        int max;
        int flag=0;
        while(i*2<=n&&flag==0){
            if(heap[i]<heap[2*i])
                max=2*i;
            else
                max=i;
            if(i*2+1<=n) {
                if (heap[max] <heap[2 * i + 1])
                    max=2*i+1;
            }
            if(max!=i) {
                swap(i, max);
                i = max;
            }
            else
                flag=1;
        }
    }
    public int deletetop(){
        int tmp=heap[1];
        heap[1]=heap[n];
        n--;
        shiftdown(1);
        return tmp;
    }
    void heapsort(){
        while(n>1){
            swap(1,n);
            n--;
            shiftdown(1);
        }
    }
    public static void main(String[] args){
        Test t=new Test();
        System.out.println("请输入结点数量");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        System.out.println("请输入结点");
        for(int i=1;i<=n;i++)
            heap[i]=sc.nextInt();
        int total=n;
        for(int i=n/2;i>=1;i--)
            t.shiftdown(i);
        t.heapsort();
        for(int i=1;i<=total;i++)
            System.out.print(heap[i]+" ");
    }
}
/*
99 5 36 7 22 17 46 12 2 19 25 28 1 92
 */

一个是取最小堆顶部值输出再调换,轮次进行,一个是最大堆最大值调换到底部,然后底部减一,继续取当前最大值(除了最大值之外的n-1个数比较),再减一,依次进行,直到全部调换完成后再输出。
专注太难了,晚饭后就玩儿到现在,果然我只有午夜能静得下心来。
7.4 并查集
试了一下,只有令右结点的祖宗结点的父结点是左结点才行,如果只令右结点的祖宗结点是左结点的话,那么他原本的父结点就会脱节,这也是为什么sum输出为6。这是个坑哪~~

import java.util.Scanner;

class Test{
    static int n;
    static int[] f=new int[101];
    public void init(){
        for(int i=1;i<=n;i++)
            f[i]=i;
    }
    public int getf(int x){
        if(f[x]==x)
            return x;
        else {
            f[x]=getf(f[x]);
            return f[x];
        }
    }
    public void merge(int x,int y){
        int t1=getf(x);
        int t2=getf(y);
        if(t1!=t2){
            f[getf(y)]=x;
        }
    }
    public static void main(String[] args){
        Test t=new Test();
        int m;
        System.out.println("请输入强盗和线索的数量");
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();//robbers
        m=sc.nextInt();//clues
        t.init();
        System.out.println("请输入线索");
        for(int i=1;i<=m;i++){
            int r1=sc.nextInt();
            int r2=sc.nextInt();
            t.merge(r1,r2);
        }
        int sum=0;
        for(int i=1;i<=n;i++){
            if(t.getf(i)==i) {
                sum++;
            }
        }
        System.out.println(sum);

    }
}
/*
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
 */

第七章也就此结束啦,第八章是其他算法的扩展,应该不会很细了,我打算总结一下前面的345章再继续。
晚安~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值