java常用的一些算法和数据结构理论总结

最近看了java的算法,也写了一些代码,但是没有进行对其练习,接下来准备在刷题网站上多练练习一下,这里现将这些基本的如何实现的步骤和思想来分享给大家,希望和大家一起进步,

目录

ArrayList实现原理:

   LinkedList的实现原理:

    双端链表:

      双向链表:

队列:

  栈:

    树:

    Hash表:

    图:

        冒泡排序:

  快速排序

  选择排序:

   插入排序:

        希尔拍序:


ArrayList实现原理:


        底层还是数组,
        首先在构造方法中初始化一个默认的大小的数组
        在有参构造中初始化一个可以指定的大小
        添加:
            循环遍历数组,在都未放数据的时候初始化list的可放数据长度,
            在index==-1时,说明要进行扩容,创建新的数组,使得他的长度为原来的2倍 ,将原来的数组中的数据copy到新的数组,这里
            是用的System中的类进行copy的   
            同样也可以创建之后使用循环遍历然后添加到新的数组中,
            并将新的引用指向旧的引用,同时对最后一个进行赋值
            如没有则进行对其的直接添加
        删除:更具下标删除
            创建一个新的对象然后令这个对象的这个index赋值为null,最终使其返回
            另一种是直接把其的对象设置为小的就可以了
        修改:
            获得这个指定的下标的数组的数据,然后令其为新的数据,最后返回这个修改后的引用
        查找:
            直接通过下标返回其对对应的数据
        查看:
            通过瞎混遍历就可以进行给显示


   LinkedList的实现原理:


        需要一个节点对象;
        节点对象的实现:
            需要数据域,和指针域,前一个指针域
        链表需要初始化:
            初石化头结点;
        插入节点:
            创建一个node节点,然后把下一个节点指向添加的节点,然后把节点给头结点
        删除头节点:
            先把头结点的数据给找到,然后令这个节点指向下一个节点:
             Node temp=first;//然后把这个节点指向第一个节点first=temp.next;return temp;       
        显示:
            把当前节点指向头结点,当前界定啊不为null时,显示出data,让当前的节点指向下一个节点
        查找: 
            通过value查找,一直循环到等于这个值时,当下个节点为null,停止,当前节点,指向下一个节点,并返回节点
        删除:
            删除的时候需要知道当前节点的,和当前节点的前一个节点,
            令当前节点指向前一个节点,并让当前节点指向下一个节点,


    双端链表:


        需要初始化头结点和尾节点
        插入节点:
                头结点插入:
                    从头结点后进行插入 要对链表判断,判断是否weinul。如果weinull.则设置尾结点为新添加的结点;

                尾节点插入:
                    从尾节点进行插入,判断是否为null,为空设置头结点为当前节点,否者令其last的下一个节点为当前插入的节点,
                    将last节点置位当前插入的节点
        头结点删除:
            从头部删除的第一个节点:判断头结点是否有下一个结点,如果没有则设置尾节点为null
            令头结点的下个节点为当前的头结点并将其返回
        查找:通过值查找
            令其当前节点为头结点,循环判断当前节点的值时否相同,当下一个节点为null则终止循环,当前元素指向下一个元素
        删除返回 
            删除的时候需要知道当前节点的,和当前节点的前一个节点,
            令当前节点指向前一个节点,并让当前节点指向下一个节点,  

  
    双向链表:


        插入节点:  
            从头结点后进行插入 :
                要对链表判断,判断是否weinul。如果weinull.则设置尾结点为新添加的结点;,如果不为null,设置头结点的前一个结点为新添加的结点
            从尾节点插入:
                从尾节点进行插入:如果链表为null则直接设置头结点为新添加的结点,否则设置尾结点的后一个结点为新添加结点,同时设置新添加的节点的前一个结点为尾结点    
        删除:  
            从头结点删除:
                从头部删除的第一个节点:判断头结点是否有下一个结点,如果没有则设置尾节点为null,否则设置头结点的下一个结点的previous为null;
            尾节点删除:
                判断头结点是否有下一个结点,如果没有则设置头节点为null,否则设置尾结点的下一个结点的next为null;
        查找:通过值查找
            令其当前节点为头结点,循环判断当前节点的值时否相同,当下一个节点为null则终止循环,当前元素指向下一个元素
        删除返回数据
            删除的时候需要知道当前节点的,和当前节点的前一个节点,
            令当前节点指向前一个节点,并让当前节点指向下一个节点,    
   

队列:


        实现主要是数组,包含队头和队尾,
        有参构造和无参构造:初始化对列,初始化有效数据,初始化队列的长度
        添加: 只能从队尾添加
            将队尾指向最后一个元素时再添加时则会越界,否则令其数据的队尾添加,同时有效长度,增加
        删除:只能从队头删除
            直接删除对头的元素,同时把有效长度减1,并返回当前删除的value
        查看数居:
            返回当前队头的元素
    数组:
        通过定义一个数组,定义一个数据的有效长度,并通过有参构造,和无参构造方式,初始化数组, 
        添加: 
            让其arry[有效长度]=value,并使得当前的有效长度增加
        查找:返回下标
            通过遍历有效长度中的每一个值,如果有的话返回,如果没有则返回-1;
        查找:通过索引查找
            通过判断索引的值,直接返回当前索引的值
        删除: 通过下标删除
            通过遍历让当前下标的后一个指向当前数据,长度-1.
        更新:
            通过下标和值,,直接设置当前下标的值为新的值
 

  栈:


        底层是一个数数组:
        初始化数组的大小和当前的栈顶元素
        添加数据:
            直接栈顶指针增加并赋值为当前插入的值
        删除数据:
            只能从栈顶删除:让其栈顶指针-1;
        查看数据:
            arry[top]


    树:


      中能够快速的查找数据项,和插入数据项,删除数据项
        * 树的概念:
        * 路径:顺着连接节点的边从一个节点到另一个节点,所经历的节点顺序
        * 根节点:树最上面的节点称为根节点,一棵树只有一个根,而且根到任何一个节点有且只有一条路径
        * 父节点:每个节点都有一条边向上连接到另一个节点,这个节点就称是下面的节点的父节点
        * 子节点:每个节点都有一条边向下连接到另一个节点,下面的节点称为该节点的子节点
        * 叶子节点:没有子节点的节点称为叶子节点
        * 子树:每个节点都可以作为一个子树的根,它和它所有的子节点,子节点的节点组合起来就是一个子树
        * 遍历:先序,中序,后序
        * 前序:1.访问根节点,2,左子树,3.右子树
        * 中序:左 ,根, 右
        * 后序 左,右,根
        * 访问:访问一个节点是为了在这个节点上执行一些操作,如查看节点的数据项,但是如果仅仅是经过一个节点,不认为是访问了这个节点
        * 层:一个节点的层数是指从根节点开始到这个节点有多少代
    二叉树:
        树的节点最多有两个子节点,称为二叉树 
        初始化二叉树:在节点中需要有以下:
            //数据项public long data;
            //数据项public String sdata; 
            //左子节点public TreeNode leftChild;
            //右子节点public TreeNode rightChild;
        插入节点:  
              从根节点开始查找一个相应的节点,这个节点将称为新插入的节点的父节点。当父节点找到后通过判断新节点值的大小决定连接在左节点还是右节点       
            先封装节点,然后让其当前节点为root,父节点为parent=null;
            判断是否为root==null如果为null则是第一个节点,则就是根节点
            否者循环对比是往左侧走,还是右侧走,将父节点为当前节点,
                如果插入的节点数据比当前节点的数据小向左走
                current =current.leftChild;如果当前的为null,则让其父节点的左子树为当前节点,然后返回
                如果为插入的节点比当前节点的数据大,往右走
                current=current.rightChild;如果当前的为null,则让其父节点的右子树为当前节点,然后返回
        查找节点:
            从根节点开始查找一个相应的节点,在比较当前节点和要查找的节点,引用当前节点,从根节点开始,只要查找的节点不等于当前节点的数据项
                //进行比较,小于value则在右子树查找,否则在左边查找
                    让其当前节点为current=current.leftChild;或者=current.rightChild;
            最后返回当前节点
        删除头节点: 
             删除之前首先要查找要删的节点,找到节点后,这个删除的节点可能有以下情况
                * 1.该节点是叶子节点,没有子节点:要删除叶节点,只需改变该节点的父节点的引用,将指向该节点的引用设置为null就可以了
                * 2.该节点有一个子节点:改变父节点的引用,将其指向要删除的节点的子节点、
                * 3.该节点有两个子节点,要删除有两个子节点的节点,就需要使用它的中序后继来替代该节点   
        前序遍历:1.访问根节点,2.访问左子树,3.访问右子树
             传入当前的节点,访问根节点,前序遍历左子树,前序遍历右子树
             

front(TreeNode localNode){
                 //访问根节点
                 System.out.println(localNode.data+","+localNode.sdata);
                 front(localNode.leftChild);
                 front(localNode.rightChild);   
             }


        中序遍历:左,根,右
           

            center(TreeNode localNode){
                center(localNode.leftChild);
                //访问根节点
                System.out.println(localNode.data+","+localNode.sdata);
                center(localNode.rightChild);
            }


        后序遍历:左右根
           

            last(TreeNode localNode){
                last(localNode.leftChild);
                last(localNode.rightChild);
                //访问根节点
                System.out.println(localNode.data+","+localNode.sdata);    
            }


    Hash表:


         底层用linklist[]数组实现
          先进行初始化数组的大小
          进行hashcode的来实现对其hash化:
            *     1直接将关键字作为索引,
            *         将字母转换为AscII吗然后进行相加
            *         幂的连乘
            *         压缩可选值
                开放地址法。链地址法
          插入数据:
            通过关键字来插入数据,其中数据包括关键字和数据添加,
          查找数据:
            通过hashcode来返回


    图:


      图是一种和树想象的数据结构,通常有固定的形状 
        * 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合。
        *      无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示。
        *      对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D};
        *      边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}:
        *有向图:若从顶点Vi到Vj的边是有方向的,则成这条边为有向边,也称为弧(Arc)。
        *用有序对(Vi,Vj)标示,Vi称为弧尾,Vj称为弧头。如果任意两条边之间都是有向的,则称该图为有向图。   
        *图的存储结构:
        *    邻接矩阵:
        *  邻接表:   
        * 图的遍历:从图中某个顶点出发访遍图中其余顶点,且使每个顶点仅被访问依次,这一过程叫做图的遍历.
        遍历方法: 
                深度优先遍历和广度优先遍历
        深度优先遍历
                图中某个顶点出发v出发,访问此顶点,然后从v的未被访问的邻接点出发深度优先便利图,知道图中所有和v有相同路径的顶点都被访问
        广度优先遍历
                    广度优先遍历(Breadth_First_Search)又称为广度优先搜索,简称BFS。 
          实现一个图必须包括一个顶点类:
            其中包括lable,和是否被访问过:
        初始化 时需要顶点数组,邻接矩阵数组,顶点的最大数目,当前顶点,栈,
        初始化图:
               

 public Graph() {
                    vertexList = new Vertex[maxSize];
                    adjMat = new int[maxSize][maxSize];
                    for(int i = 0; i < maxSize; i++) {
                        for(int j = 0; j < maxSize; j++) {
                            adjMat[i][j] = 0;
                        }
                    }
                    nVertex = 0;
                    stack = new Stack();
                }         

     
        添加顶点:
                vertexList[nVertex++]=new Vertex(label);
        添加边:
                adjMat[start][end]=1;
                adjMat[end][start]=1;
        深度优先搜索:
             由顶点一直向下搜索   
             1.如果可能,访问一个邻接的未访问过的顶点,标记他并把它放入到栈中,
             2.如果不能执行1时,如果栈不为null,就充栈中弹出一个顶点
             3.当不能执行1和2,时就完成了整个搜索过程
        广度优先搜索:
            一层一层的搜索
            1.访问下一个邻接的未访问过的顶点,这个顶点必须是当前节点的邻接点标记他,并且,把它插入到队列中
            2,如果无法执行规则1,那么久从队列头取出一个顶点,并使其作为当前顶点,
            3,当队列不能执行规则2时,就完成了整个搜索过程   
    排序:


        冒泡排序:


                思想左右对比,然后是对应的左面大的话不动,
               

public static void bubblesort(long [] arry){
                    for(int i=0;i<arry.length;i++){
                        for(int j=arry.length-1;j>i;j--){
                            if (arry[j]<arry[j-1]) {
                                //进行交换
                                long temp;
                                temp=arry[j];
                                arry[j]=arry[j-1];
                                arry[j-1]=temp;
                            }
                        } 
                    }
                }

 


  快速排序


                通过一个数组划分为若干个子数组,然后通过递归调用自身为每一个子数组进行快速排序
                 设定关键字比关键字大的设定为一组,比关键字小的放为一组,设置数组最右端的数据为关键字
     

  选择排序:


                从未排的序列中找最大或最小的元素,存放在序列的起始位置,然后再从剩余的未排序元素中继续寻找最小的(大)的元素,然后放到已排序序列的末位 
           

 public static void selectSort(long[] arry){
                int k=0;
                long temp=0;
                for(int i=0;i<arry.length-1;i++){
                    k=i;//k指向(每次循环的首个)
                    for(int j=i;j<arry.length;j++){
                        if (arry[j]<arry[k]) {
                            k=j;
                        }
                    }
                    //指向的为最小的数据
                    temp=arry[i];
                    arry[i]=arry[k];
                    arry[k]=temp;
                }
            }


   插入排序:


                通过构建一个有序数列,对于未排序的数据在已排序的数据中进行向前扫描,找到相应的位置插入,通常采用in-place排序,因而在从后向前扫描过程中,需要反复
                把已排序元素逐步向后挪位,为新的元素提供插入的空间。
                缺陷:假如很小的数据在靠右端的位置,那么要将该数据排序到正确的位置上,则所有的中间的数据都需要向右移动
               

public static void insertsort(long[]  arry){
                    //从数组的2号位置开始 i=1;
                    long temp=0;
                    for(int i=1;i<arry.length;i++){
                        temp=arry[i];//指向当前的这个
                        int j=i;
                        while (j>0 && arry[j]>=temp) {
                            arry[j]=arry[j-1];//右移
                            j--;
                        }
                        arry[j]=temp;
                    }
                }    


        希尔拍序:


            通过加大插入排序中元素之间的间隔,并对这些间隔的元素,进行插入排序,从而使得数据可以大浮动的,当完成该间隔的排序后,希尔排序会减少数据的间隔在进行排序,依次进行下去
           

 public static void shellsort(long[] arry){
                //初始化一个间隔
                int h=1;
                
                //计算最大间隔
                while(h<arry.length/3 ){
                    h=h*3+1;
                }
                
                while(h>0){
                    //进行插入排序
                    long temp=0;
                    for(int i=h;i<arry.length;i++){
                        temp=arry[i];//指向当前的这个
                        int j=i;
                        while (j> h-1 && arry[j-h]>=temp) {
                            arry[j]=arry[j-h];//右移
                            j-=h;
                        }
                        arry[j]=temp;
                    }    
                    //减小间隔
                    h=(h-1)/3;
                }
            }


           

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值