数据结构—cloneable&&二叉树

来源:互联网 发布:阿国网络随笔诈骗 编辑:程序博客网 时间:2024/05/16 10:40

1介绍cloneable接口,并引申与它相关的知识点:
2二叉树相关知识点:
一、cloneable接口

首先强调一个问题,cloneable接口时空的,clone方法不是cloneable的方法!!!clone时object的方法,方法原型为

protected object clone () throws CloneNotSupportException

这里有两个细节,一 返回值是object; 二 类型为protected;三是抛出的异常

先说第一个,这里的object实际上是不用修改的,但我们可以思考一些java深入的东西,“协变”。

协变最直观的表现形式就是针对父类方法的重写,我们可以修改重写方法的返回值类型,但必须是父类方法返回值类型的子类。

第二个 clone方法的类型修饰符号是protected,先抛出理念,设计者不希望每个子类都简单拥有clone方法,需要使用者仔细的考量一下。

类的修饰符有两种,public和默认,public随意访问,默认只允许同包内才可以访问,或者不同包下实现继承也可以访问。

方法的修饰符有四种,从大到小依次为public,protected,默认,private

子类继承父类方法,修饰符可以不同,但是必须要比父类型的修饰符范围要宽,另外需要注意的是私有类型private除外,这个不可以被重写。

 同类同包子类同包非子类不同包子类不同包非子类publicprotected 默认  private    第三个是异常抛出的规定,子类重写父类的方法,要么不跑出异常,要么抛出的异常要比父类的异常要小。这里,要么方法上抛

CloneNotSupportedException
要么什么都不写
@Overridepublic A clone(){    A a=null;    try {        a = (A)super.clone();    } catch (CloneNotSupportedException e) {        e.printStackTrace();    }    a.age=1;    return a;}
clone方法需要注意的地方,1必须调用super.clone()方法返回一个新的对象,但是这里的super是object,object返回的应该也是object,但是object可以直接强制转化为A类型吗?不是会报错吗,这里还没有弄清楚。2必须捕获异常或者抛出异常。上面写的是一种标准的clone实现手段。

二、二叉树

1满二叉树:叶子节点在最底层,非叶子节点都有两个孩子

2完全二叉树:除了最后一层都是满的,最后一层从左到右填充

3平衡二叉树:每个节点左右子树的高度差不超过1

4完全平衡二叉树:每个节点有两颗高度完全相等的子树

平衡不一定完全,完全一定平衡

满二叉树的节点个树为2^h-1,因此树的深度为log(n+1),对于完全二叉树,则树深为log(n+1)向上取整。

层序遍历是广度优先,前序遍历是深度优先。

中缀表达式、前缀表达式、后缀表达式分别对应树的中序遍历、前序遍历、后序遍历

普通树转化为二叉树的核心是左孩子是第一个孩子,右孩子是第一个兄弟。

二叉树的删除比较麻烦

考虑三种情况

1叶子节点删除

2只有左孩子或右孩子

3左孩子右孩子都有,考虑删除左孩子的最右孩子

void DeleteVal(Tree root,int val){    Tree p =root,s=root;//p->parent,s->son    while (s.val!=val&&s!=null){//找到要删除的元素        if (val<s.val){            p=s;            s=s.left;        }else{            p=s;            s=s.right;        }    }    if (s==null){//如果要删除的是null,返回        System.out.println("no point");        return;    }    if (s.left==null&&s.right==null){//第一种情况,叶子节点,直接删除,父节点指向空        if (s==root){            root=null;//如果s是根结点,删除根结点        }else {            //判断叶子节点是父节点的左孩子还是右孩子            if(p.left==s)p.left=null;            else p.right=null;        }    }else if (s.left==null||s.right==null){//第二种情况,只有一个孩子        if (s.left!=null){//只有左孩子            if (root==s)root=s.left;//判根            else{                //如果删除节点是左孩子,父节点的左指针指向左孩子的左孩子                if (p.left==s)p.left=s.left;                //如果右孩子,父节点的右指针指向右孩子的左孩子                else p.right=s.left;            }        }else {//只有右孩子            if (root==s)root=s.right;            else{                if (p.left==s)p.left=s.right;                else p.right=s.right;            }        }    }else if (s.left!=null&&s.right!=null){//第三种情况        Tree np=s;        Tree n=s.right;        while (n.left!=null){//找到右孩子的最左节点            np=n;            n=n.left;        }        s.val=n.val;//值替换        if (s==np)s.right=n.right;//如果右孩子没有左孩子,直接替换        else np.left=n.right;//如果右孩子有左孩子,删除左孩子    }}