Set和List区别

  1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
  2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
  3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变
    <实现类有ArrayList,LinkedList,Vector> 。
package 集合;
import java.util.ArrayList;
public class ArrayListDemo {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ArrayList<String> alist=new ArrayList<String>();
  alist.add("qq");
  alist.add("abc");
  alist.add("aaa");
  alist.add("abc");
  alist.add("aaa");
  for(int i=0;i<alist.size();i++) {
   System.out.println(alist.get(i));
  }
  }
  }

运行结果如下:

qq
 abc
 aaa
 abc
 aaa
package 集合;
import java.util.HashSet;
import java.util.Set;
public class HastSetDemo {
public static void main(String[] args) {
  // TODO Auto-generated method stub
  Set<String> sets=new HashSet<String>();
  sets.add("aaa");
  sets.add("bbb");
  sets.add("ccc");
  sets.add("aaa");
  for(String str:sets) {
   System.out.println(str);
  }
  }
  }

运行结果如下:

aaa
 ccc
 bbb

二叉树

定义
二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。
类型

  1. 完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1)
    的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
  2. 满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
  3. 平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
package Tree;
public class Test {
public static void main(String[] args) {
  // TODO Auto-generated method stub
  int[] arrays = { 2, 3, 1, 4, 5 };
  // 动态创建树
  TreeRoot root = new TreeRoot();
  for (int value : arrays) {
   TreeRoot.createTree(root, value);
  }
  // 先序遍历树
  TreeRoot.preTraverseBTree(root.getTreeRoot());
  System.out.println("---------------公众号:Java3y");
  // 中序遍历树
  TreeRoot.inTraverseBTree(root.getTreeRoot());
  System.out.println("---------------公众号:Java3y");
 }
 }
package Tree;
public class TreeNode {
 // 左节点(儿子)
 private TreeNode lefTreeNode;
 // 右节点(儿子)
 private TreeNode rightNode;
 // 数据
 private int value;
 public TreeNode getLefTreeNode() {
  return lefTreeNode;
 }
 public void setLefTreeNode(TreeNode lefTreeNode) {
  this.lefTreeNode = lefTreeNode;
 }
 public TreeNode getRightNode() {
  return rightNode;
 }
 public void setRightNode(TreeNode rightNode) {
  this.rightNode = rightNode;
 }
 public int getValue() {
  return value;
 }
 public void setValue(int value) {
  this.value = value;
 }
 public TreeNode(int value) {
  this.value = value;
 }
}
package Tree;
public class TreeRoot {
 private TreeNode treeRoot;
    public TreeNode getTreeRoot() {
        return treeRoot;
    }
    public void setTreeRoot(TreeNode treeRoot) {
        this.treeRoot = treeRoot;
    }
    /**
     * 动态创建二叉查找树
     *
     * @param treeRoot 根节点
     * @param value    节点的值
     */
    public static void createTree(TreeRoot treeRoot, int value) {
        //如果树根为空(第一次访问),将第一个值作为根节点
        if (treeRoot.getTreeRoot() == null) {
            TreeNode treeNode = new TreeNode(value);
            treeRoot.setTreeRoot(treeNode);
        } else  {
            //当前树根
            TreeNode tempRoot = treeRoot.getTreeRoot();
            while (tempRoot != null) {
                //当前值大于根值,往右边走
                if (value > tempRoot.getValue()) {
                    //右边没有树根,那就直接插入
                    if (tempRoot.getRightNode() == null) {
                        tempRoot.setRightNode(new TreeNode(value));
                        return ;
                    } else {
                        //如果右边有树根,到右边的树根去
                        tempRoot = tempRoot.getRightNode();
                    }
                } else {
                    //左没有树根,那就直接插入
                    if (tempRoot.getLefTreeNode() == null) {
                        tempRoot.setLefTreeNode(new TreeNode(value));
                        return;
                    } else {
                        //如果左有树根,到左边的树根去
                        tempRoot = tempRoot.getLefTreeNode();
                    }
                }
            }
        }
        
    }
    /**
     * 先序遍历
     * @param rootTreeNode  根节点
     */
    public static void preTraverseBTree(TreeNode rootTreeNode) {
        if (rootTreeNode != null) {
            //访问根节点
            System.out.println(rootTreeNode.getValue());
            //访问左节点
            preTraverseBTree(rootTreeNode.getLefTreeNode());
            //访问右节点
            preTraverseBTree(rootTreeNode.getRightNode());
        }
    }
    /**
     * 中序遍历
     * @param rootTreeNode  根节点
     * 
     */
    public static void inTraverseBTree(TreeNode rootTreeNode) {
        if (rootTreeNode != null) {
            //访问左节点
            inTraverseBTree(rootTreeNode.getLefTreeNode());
            //访问根节点
            System.out.println(rootTreeNode.getValue());
            //访问右节点
            inTraverseBTree(rootTreeNode.getRightNode());
        }
    }
}

运行结果如下:

2
 1
 3
 4
 5 
 1
 2
 3
 4
 5


递归
程序调用自身的编程技巧称为递归。递归做为一种算法在程序设计语言中广泛应用。但是如果没终止条件会造成死循环,所以递归代码里要有结束自调自的条件。

注意:

  1. 递归就是方法里调用自身。
  2. 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
  3. 递归算法代码显得很简洁,但递归算法解题的运行效率较低。所以不提倡用递归设计程序。
  4. 在递归调用的过程中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等,所以一般不提倡用递归算法设计程序。
  5. 在做递归算法的时候,一定把握出口,也就是做递归算法必须要有一个明确的递归结束条件。这一点是非常重要的。其实这个出口就是一个条件,当满足了这个条件的时候我们就不再递归了。
package Temp;
public class unmm {
 public int sum(int num) {
  if(num==1) {
  return 1;
  }else {
   return num+sum(num-1);
  }
 }
}
package Temp;
public class Test {
unmm m=new unmm();
  System.out.println(m.sum(100));
 }

运行结果如下:

5050