zoukankan      html  css  js  c++  java
  • 树(234树插入查找显示)

    每个节点最多可以存三个数据项
    不存在空节点
    叶子结点可以有数据项而没有子节点
    数据总是插入叶节点中
    有一个数据项的节点总是有两个子节点
    有两个数据项的节点总是有三个子节点
    有三个数据项的节点总是有四个子节点

    //数据项
    public class DataItem {
        public long dData;
        public DataItem(long dd) {
            dData=dd;
        }
        public void displayNode() {
            System.out.print("/"+dData);
        
        }
    
    }
    //节点
    public class Node {
        public static final int order=4;//最多有四个子节点,三个数据项,所以即数据项数组最大值order-1,子节点是order
        private int numItems;//当前数据项个数
        private Node parent;//父节点
        private Node[] childArray=new Node[order];//子节点数组
        private DataItem[] itemArray=new DataItem[order-1];//数据项数组
        //根据下标取子节点数组中某个子节点
        public Node getChild(int childNum) {
            return childArray[childNum];
        }
        //取父节点(父节点只有一个)
        public Node getParent() {
            return parent;
        }
        //判断当前节点是否是叶子结点
        public boolean isLeaf() {//判断当前节点的子节点是否为空(判断第一个是否为空就行)
            return (childArray[0]==null?true:false);
        }
        //取数据项个数
        public int getNumItems() {
            return numItems;
        }
        //根据索引取具体的数据项
        public DataItem getItem(int index) {
            return itemArray[index];
        }
        //判断存数据项的数组是否是满的(数据项数组是否为满)
        public boolean isFull() {
            return (numItems==order-1);
        }
        //加入子节点(将对应的子节点放到数组中,childNum为数组中的索引)双向的
        public void connectChild(int childNum,Node child) {
            childArray[childNum]=child;
            if(child!=null) child.parent=this;//插入的节点不能为空
        }
        //删除子节点(根据索引,将数组为空就行)
        public Node disconnectChild(int childNum) {
            Node tempNode=childArray[childNum];
            childArray[childNum]=null;
            return tempNode;
            
        }
        //查找当前节点key数据项
        public int findItem(long key) {
            for(int j=0;j<order-1;j++) {
                if(itemArray[j]==null)break;//数据项中是空的,就说明后面也没有要找的了
                else if(itemArray[j].dData==key)return j;
            }
            return -1;
        }
        //插入数据项
        public int insertItem(DataItem newItem) {
            numItems++;//插入加1
            long newKey=newItem.dData;
            //找到数据项在数组中插入的位置
            for(int j=order-2;j>=0;j--) {//从后往前找
                if(itemArray[j]==null) continue;//如果数据项为空,继续往前找,执行下一次循环
                else {//不为空进行数据比对
                    long itsKey=itemArray[j].dData;
                    if(newKey<itsKey)
                        itemArray[j+1]=itemArray[j];//如果找到的数据项小,往后移(继续循环知道找到比它大的)
                    else {
                        itemArray[j+1]=newItem;//将当前数据项直接放在最后一个
                        return j+1;//直接跳出循环,返回插入的位置
                    }
                }
                
            }
            //如果没找到比它小的,都比它大,最后在0这个位置插入数据项
            //插入的位置是0
            itemArray[0]=newItem;
            return 0;
        }
        //删除数据项
        public DataItem remove() {//直接删最后一个
            DataItem temp=itemArray[numItems-1];
            itemArray[numItems-1]=null;
            numItems--;
            return temp;
        }
        //显示
        public void display() {
            for(int j=0;j<numItems;j++)
                itemArray[j].displayNode();
            System.out.println("/");//全部输出之后,换行,每个节点作为一行输出
                
        }
        
        
        
        
    
        
        
        
        
        
    
    }
    public class Tree234 {
        Node root=new Node();
        //查找数据
        public int find(long key) {
            Node curNode=root;
            int childNumber;
            while(true) {
                if((childNumber=curNode.findItem(key))!=-1)
                    return childNumber;//找到了,返回位置
                else if(curNode.isLeaf())//如果上面没有找到,且是叶子节点,就没法继续往下找了。找不到
                    return -1;//没有找到
                else 
                    curNode=getNextChild(curNode,key);//如果不是叶子结点,就在它的某个子节点中找
            }
        }
        //获取theNode的子节点中要寻找的子节点
        public Node getNextChild(Node theNode,long theValue) {
            int j;
            int numItems=theNode.getNumItems();//根据theNode的数据项个数判断节点个数
            for(j=0;j<numItems;j++) {//循环节点的数据项
                if(theValue<theNode.getItem(j).dData)//根据数据项的比对,来判断下一个比较的子节点
                    return theNode.getChild(j);
            }
            return theNode.getChild(j);
        }
        //新增数据项
        public void insert (long dValue) {
            Node curNode=root;
            DataItem tempItem=new DataItem(dValue);
            while(true) {//找到需要插入的节点
                if(curNode.isFull()) {//如果需要插入的当前节点满了,就需要拆分
                    split(curNode);//拆分为一个新的(中间的数做新的根,左数值为左边子节点作为,右数值右边子节点)
                    //重新定义curNode
                    curNode=curNode.getParent();
                    curNode=getNextChild(curNode,dValue);
                }else if(curNode.isLeaf()) {//如果是叶子结点,而且没满,等循环结束,插入
                    break;//找到节点
                }else//如果不是叶子结点,找到需要插入的叶子结点
                    curNode=getNextChild(curNode,dValue);
                
            }
            curNode.insertItem(tempItem);//插入到当前节点中
        }
        //拆分
        public void split(Node thisNode) {
            DataItem itemB,itemC;
            Node parent,child2,child3;//父节点是中间值得来的,childe2和child3是保存该节点的子节点
            int itemIndex;
            //将当前节点的数据项数组删除两个,子节点数组就得删除两个
            itemC=thisNode.remove();//删除当前节点最大数据项
            itemB=thisNode.remove();//删除第二大的,中间值
            child2=thisNode.disconnectChild(2);//删除当前节点的子节点2
            child3=thisNode.disconnectChild(3);//删除当前节点的子节点3
            //删除后thisNode就是值为索引为0的,还有索引为0,1的子节点
            Node newRight=new Node();//最大值的节点
            //插入parent(中间值)    
            if(thisNode==root) {//如果当前节点是根节点
                //创建新的根
                root=new Node();
                parent=root;
                root.connectChild(0, thisNode);//加入子节点thisNode于0位置
                
                
            }else //如果不是根
                parent=thisNode.getParent();
            //插入itemB(插入根的值)
            itemIndex=parent.insertItem(itemB);//插入数据项,返回插入的位置
            int n=parent.getNumItems();//返回数据项的个数
            for(int j=n-1;j>itemIndex;j--) {
                Node temp=parent.disconnectChild(j);//删除子节点
                parent.connectChild(j+1, temp);//插入子节点
            }
            //插入最大值
            parent.connectChild(itemIndex+1, newRight);
            newRight.insertItem(itemC);
            newRight.connectChild(0, child2);
            newRight.connectChild(1, child3);
        }
        //显示树
        public void display() {
            recDisplayTree(root,0,0);//第0层,当前节点存在的位置是父节点的节点数组的0位置
            
        }
        //显示树(递归函数)
        //childNumber为当前节点在父节点子节点数组中的索引数
        private void recDisplayTree(Node thisNode,int level,int childNumber) {
            System.out.print("leve="+level+"child="+childNumber+" ");
            thisNode.display();
            
            int numItems=thisNode.getNumItems();//节点的数据量,可以知道该节点有几个子节点
            for(int j=0;j<numItems+1;j++) {
                Node nextNode=thisNode.getChild(j);
                if(nextNode!=null)
                    recDisplayTree(nextNode,level+1,j);//下层递归
                else return;
                
            }
        }
    
    }
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Test {
        public static void main(String[] agrs) throws IOException{
            long value;
            Tree234 theTree=new Tree234();
            theTree.insert(50);
            theTree.insert(40);
            theTree.insert(60);
            theTree.insert(30);
            theTree.insert(70);
            while(true) {
                System.out.print("Enter first letter of show,isnert,find:");
                int choice=getchar();
                switch(choice){
                    case's':
                        theTree.display();
                        break;
                    case 'i':
                        System.out.print("Enter value to insert:");
                        value=getInt();
                        theTree.insert(value);
                        break;
                    case 'f':
                        System.out.println("Enter value to find:");
                        value=getInt();
                        int found=theTree.find(value);
                        if(found!=-1) {
                            System.out.print("Found "+value);
                            
                        }else
                            System.out.print("not"+value);
                        break;
                    
                   default:
                            System.out.println("无效的输入");
                        
                        
                        
                }
            }
        }
        public static String getString()throws IOException{
            InputStreamReader isr=new InputStreamReader(System.in);
            BufferedReader br=new BufferedReader(isr);
            return br.readLine();
            }
        public static char getchar() throws IOException{
            return getString().charAt(0);
            
        }
        public static int getInt() throws IOException{
            String s=getString();
            return Integer.parseInt(s);
        }
        
    
    }
  • 相关阅读:
    ASP.NET MVC 重点教程一周年版 第二回 UrlRouting
    ASP.NET MVC 重点教程一周年版 第三回 Controller与View
    DynamicData for Asp.net Mvc留言本实例 下篇 更新
    Asp.net MVC视频教程 18 单选与复选框
    使用ASP.NET MVC Futures 中的异步Action
    ASP.NET MVC RC 升级要注意的几点
    ATL、MFC、WTL CString 的今生前世
    msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
    关于Windows内存的一些参考文章
    Windows访问令牌相关使用方法
  • 原文地址:https://www.cnblogs.com/S-Mustard/p/7743640.html
Copyright © 2011-2022 走看看