【算法】堆,最大堆(大顶堆)及最小堆(小顶堆)的实现

2023-10-27

此坑待埋。

点击打开漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析链接



白话经典算法系列之七 堆与堆排序



二叉排序树与二叉堆


堆排序(注:这篇文章说明了如何从一个数组构建一个最大堆,推荐看)


最大堆的插入/删除/调整/排序操作(图解+程序)(JAVA)


下面来说一说具体算法。


堆排序解释第一篇(描述不太清楚)

1.堆

  堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

  Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

  即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

  堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

   利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

    其基本思想为(大顶堆):

    1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

    2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n]; 

    3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

    操作过程如下:

     1)初始化堆:将R[1..n]构造为堆;

     2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

    因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

    下面举例说明:

     给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

    首先根据该数组元素构建一个完全二叉树,得到

 
 然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

20和16交换后导致16不满足堆的性质,因此需重新调整

这样就得到了初始堆。


即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。

此时3位于堆顶不满堆的性质,则需调整继续调整

 这样整个区间便已经有序了。
    从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。
【ok,从一个原始数组调整成为一个堆,想必已经很清楚了,那么如何从堆里面获取数据变成已经排好序的数组呢?】
下面是一个例子:

    0.待排序序列:

         A[6]={3,5,8,9,1,2},  

        1.建堆后(建堆过程参见4.4):

        A[6]={9,3,8,5,1,2}

       2.9和2交换,然后把9从堆中去掉后:

         A[6]={2,3,8,5,1,9}

      3.筛选法调整堆A[5]={2,3,8,5,1}后(调整过程参见4.3):

       A[6]={8,3,2,5,1,9}

      4.堆顶记录与最后一个记录互换,重复第二步,但是堆顶记录和最后一个记录的值变了


【附上另一篇文章--- 最大堆的插入/删除/调整/排序操作(图解+程序)(JAVA)

最大堆的插入/删除/调整/排序操作(图解+程序)(JAVA)

 堆有最大堆和最小堆之分,最大堆就是每个节点的值都>=其左右孩子(如果有的话)值的完全二叉树。最小堆便是每个节点的值都<=其左右孩子值的完全二叉树。 

  设有n个元素的序列{k1,k2,...,kn},当且仅当满足下列关系时,称之为堆。 
 

堆的三种基本操作(以下以最大堆为例): 
⑴最大堆的插入    

    由于需要维持完全二叉树的形态,需要先将要插入的结点x放在最底层的最右边,插入后满 足完全二叉树的特点; 
  然后把x依次向上调整到合适位置满足堆的性质,例如下图中插入80,先将80放在最后,然后两次上浮到合适位置. 
  时间:O(logn)。  “结点上浮” 
 

程序实现: 
 //向最大堆中插入元素, heap:存放堆元素的数组
    public static void insert(List<Integer> heap, int value) { 
       //在数组的尾部添加
        if(heap.size()==0)
          heap.add(0);//数组下标为0的位置不放元素
        heap.add(value); 
        //开始上升操作 
       // heapUp2(heap, heap.size() - 1); 
        heapUp(heap, heap.size() - 1); 
 
    } 
 
    //上升,让插入的数和父节点的数值比较,当大于父节点的时候就和父节点的值相交换 
    public static void heapUp(List<Integer> heap, int index) { 
 
        //注意由于数值是从下标为1开始,当index = 1的时候,已经是根节点了 
        if (index > 1) { 
            //求出父亲的节点 
            int parent = index / 2; 
 
            //获取相应位置的数值 
            int parentValue = (Integer) heap.get(parent); 
            int indexValue = (Integer) heap.get(index); 
            //如果父亲节点比index的数值小,就交换二者的数值 
            if (parentValue < indexValue) { 
                //交换数值 
                swap(heap, parent, index); 
                //递归调用 
                heapUp(heap, parent); 
            } 
 
        } 
    } 


⑵删除  
   操作原理是:当删除节点的数值时,原来的位置就会出现一个孔,填充这个孔的方法就是, 
把最后的叶子的值赋给该孔并下调到合适位置,最后把该叶子删除。 
  
如图中要删除72,先用堆中最后一个元素来35替换72,再将35下沉到合适位置,最后将叶子节点删除。 
   “结点下沉” 

 
【勘误】
大家看到上面的删除过程是不是觉得很容易明白?
我也如此认为,直到我写程序时候出现了问题才重新审视删除算法的正确性。
譬如说:现在有一个最小堆,如下图:
现在我选中了93,并且要删除它,接下来会发生什么事?
接下来就是这个算法的结果了:
对,当节点没有空间下沉的时候它就会无所事事,结果导致不对了。
这种情况下面我们可以借用插入过程的上浮调整方式,从最下面开始向上调整。


程序:
 /**
     * 删除堆中位置是index处的节点
     * 操作原理是:当删除节点的数值时,原来的位置就会出现一个孔
     * 填充这个孔的方法就是,把最后的叶子的值赋给该孔,最后把该叶子删除
     * @param heap 
     */ 
    public static void delete(List<Integer> heap,int index) { 
        //把最后的一个叶子的数值赋值给index位置 
        heap.set(index, heap.get(heap.size() - 1)); 
        //下沉操作 
        //heapDown2(heap, index); 
        heapDown(heap, index); 
        //把最后一个位置的数字删除 
        heap.remove(heap.size() - 1); 
    } 
    /**
     * 递归实现
     * 删除堆中一个数据的时候,根据堆的性质,应该把相应的位置下移,才能保持住堆性质不变
     * @param heap 保持堆元素的数组
     * @param index 被删除的那个节点的位置
     */ 
    public static void heapDown(List<Integer> heap, int index) { 
        //因为第一个位置存储的是空值,不在考虑之内 
        int n = heap.size() - 2; 
 
        //记录最大的那个儿子节点的位置 
        int child = -1; 
 
        //2*index>n说明该节点没有左右儿子节点了,那么就返回 
        if (2 * index > n) { 
            return; 
        } //如果左右儿子都存在 
        else if (2 * index < n) { 
 
            //定义左儿子节点 
            child = 2 * index; 
            //如果左儿子小于右儿子的数值,取右儿子的下标 
            if ((Integer) heap.get(child) < (Integer) heap.get(child + 1)) { 
                child++; 
            } 
 
        }//如果只有一个儿子(左儿子节点) 
        else if (2 * index == n) { 
            child = 2 * index; 
        } 
 
        if ((Integer) heap.get(child) > (Integer) heap.get(index)) { 
            //交换堆中的child,和index位置的值 
            swap(heap, child, index); 
 
            //完成交换后递归调用,继续下降 
            heapDown(heap, child); 
        } 
    } 
 


⑶初始化 
方法1:插入法: 
  从空堆开始,依次插入每一个结点,直到所有的结点全部插入到堆为止。 
  时间:O(n*log(n)) 
  方法2:调整法: 
    序列对应一个完全二叉树;从最后一个分支结点(n div 2)开始,到根(1)为止,依次对每个分支结点进行调整(下沉),
以便形成以每个分支结点为根的堆,当最后对树根结点进行调整后,整个树就变成了一个堆。 
  时间:O(n) 
对如图的序列,要使其成为堆,我们从最后一个分支结点(10/2),其值为72开始,依次对每个分支节点53,18,36 45进行调整(下沉). 
 
 
 
【补充说明】
如何获取相应数组序列?
方法是依次将堆的根节点的小数记下,然后删除根节点,如此反复直到堆为空。上面提到了删除操作,每次删除之后都是要调整堆让堆的性质不变,即根节点必为最大值或最小值,明白了吗?
程序:
     /*根据树的性质建堆,树节点前一半一定是分支节点,即有孩子的,所以我们从这里开始调整出初始堆*/  
     public static void adjust(List<Integer> heap){
        for (int i = heap.size() / 2; i > 0; i--)  
            adjust(heap,i, heap.size()-1);  
          
        System.out.println("=================================================");
        System.out.println("调整后的初始堆:");
          print(heap);
      }
    /** 
     * 调整堆,使其满足堆得定义 
     * @param i 
     * @param n 
     */  
    public static void adjust(List<Integer> heap,int i, int n) {  
       
        int child;  
        for (; i <= n / 2; ) {  
            child = i * 2;  
            if(child+1<=n&&heap.get(child)<heap.get(child+1))  
                child+=1;/*使child指向值较大的孩子*/  
            if(heap.get(i)< heap.get(child)){  
                swap(heap,i, child);  
                /*交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整*/  
                i = child;  
               
            }  else break;
        }  
    }  


(4)最大堆排序   

 //对一个最大堆heap排序
    public static void heapSort(List<Integer> heap) {  
       
        for (int i = heap.size()-1; i > 0; i--) {  
         /*把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可排好序*/  
            swap(heap,1, i);  
            adjust(heap,1, i - 1);  
        }  
    }  


(5)完整的代码 
import java.util.*; 
 
/**
 *实现的最大堆的插入和删除操作
 * @author Arthur
 */ 
public class Heap { 
     /**
     * 删除堆中位置是index处的值
     * 操作原理是:当删除节点的数值时,原来的位置就会出现一个孔
     * 填充这个孔的方法就是,把最后的叶子的值赋给该孔,最后把该叶子删除
     * @param heap 一个最大堆
     */ 
    public static void delete(List<Integer> heap,int index) { 
        //把最后的一个叶子的数值赋值给index位置 
        heap.set(index, heap.get(heap.size() - 1)); 
        //下沉操作 
        //heapDown2(heap, index); 
        heapDown(heap, index); //节点下沉
        //把最后一个位置的数字删除 
        heap.remove(heap.size() - 1); 
    } 
 
 
    /** 
     * 节点下沉递归实现
     * 删除一个堆中一个数据的时候,根据堆的性质,应该把相应的位置下移,才能保持住堆性质不变
     * @param heap 保持最大堆元素的数组
     * @param index 被删除的那个节点的位置
     */ 
    public static void heapDown(List<Integer> heap, int index) { 
        //因为第一个位置存储的是空值,不在考虑之内 
        int n = heap.size() - 2; 
 
        //记录最大的那个儿子节点的位置 
        int child = -1; 
 
        //2*index>n说明该节点没有左右儿子节点了,那么就返回 
        if (2 * index > n) { 
            return; 
        } //如果左右儿子都存在 
        else if (2 * index < n) { 
 
            //定义左儿子节点 
            child = 2 * index; 
            //如果左儿子小于右儿子的数值,取右儿子的下标 
            if ((Integer) heap.get(child) < (Integer) heap.get(child + 1)) { 
                child++; 
            } 
 
        }//如果只有一个儿子(左儿子节点) 
        else if (2 * index == n) { 
            child = 2 * index; 
        } 
 
        if ((Integer) heap.get(child) > (Integer) heap.get(index)) { 
            //交换堆中的child,和index位置的值 
            swap(heap, child, index); 
 
            //完成交换后递归调用,继续下降 
            heapDown(heap, child); 
        } 
    } 
 
    //非递归实现 
    public static void heapDown2(List<Integer> heap, int index) { 
        int child = 0;//存储左儿子的位置 
 
        int temp = (Integer) heap.get(index); 
        int n = heap.size() - 2; 
        //如果有儿子的话 
        for (; 2 * index <= n; index = child) { 
            //获取左儿子的位置 
            child = 2 * index; 
            //如果只有左儿子 
            if (child == n) { 
                child = 2 * index; 
            } //如果右儿子比左儿子的数值大 
            else if ((Integer) heap.get(child) < (Integer) heap.get(child + 1)) { 
                child++; 
            } 
 
            //如果数值最大的儿子比temp的值大 
            if ((Integer) heap.get(child) >temp) { 
                //交换堆中的child,和index位置的值 
                swap(heap, child, index); 
            } else { 
                break; 
            } 
        } 
    } 
 
    
     //打印链表 
    public static void print(List<Integer> list) { 
        for (int i = 1; i < list.size(); i++) { 
            System.out.print(list.get(i) + " "); 
        } 
        System.out.println();
    } 
 
    //把堆中的a,b位置的值互换 
    public static void swap(List<Integer> heap, int a, int b) { 
        //临时存储child位置的值 
        int temp = (Integer) heap.get(a); 
 
        //把index的值赋给child的位置 
        heap.set(a, heap.get(b)); 
 
        //把原来的child位置的数值赋值给index位置 
        heap.set(b, temp); 
    } 
 
    //向最大堆中插入元素 
    public static void insert(List<Integer> heap, int value) { 
           //在数组的尾部添加要插入的元素
        if(heap.size()==0)
          heap.add(0);//数组下标为0的位置不放元素
        heap.add(value); 
        //开始上升操作 
       // heapUp2(heap, heap.size() - 1); 
        heapUp(heap, heap.size() - 1); 
 
    } 
 
    //节点上浮,让插入的数和父节点的数值比较,当大于父节点的时候就和节点的值相交换 
    public static void heapUp(List<Integer> heap, int index) { 
 
        //注意由于数值是从小标为一开始,当index = 1的时候,已经是根节点了 
        if (index > 1) { 
            //保存父亲的节点 
            int parent = index / 2; 
 
            //获取相应位置的数值 
            int parentValue = (Integer) heap.get(parent); 
            int indexValue = (Integer) heap.get(index); 
            //如果父亲节点比index的数值小,就交换二者的数值 
            if (parentValue < indexValue) { 
                //交换数值 
                swap(heap, parent, index); 
                //递归调用 
                heapUp(heap, parent); 
            } 
 
        } 
    } 
 
    //非递归实现 
    public static void heapUp2(List<Integer> heap, int index) { 
        int parent = 0; 
        for (; index > 1; index /= 2) { 
            //获取index的父节点的下标 
            parent = index / 2; 
 
            //获得父节点的值 
            int parentValue = (Integer) heap.get(parent); 
            //获得index位置的值 
            int indexValue = (Integer) heap.get(index); 
             
            //如果小于就交换 
            if (parentValue < indexValue) { 
                swap(heap, parent, index); 
            } 
        } 
    } 
     /*根据树的性质建堆,树节点前一半一定是分支节点,即有孩子的,所以我们从这里开始调整出初始堆*/  
     public static void adjust(List<Integer> heap){
        for (int i = heap.size() / 2; i > 0; i--)  
            adjust(heap,i, heap.size()-1);  
          
        System.out.println("=================================================");
        System.out.println("调整后的初始堆:");
          print(heap);
      }
    /** 
     * 调整堆,使其满足堆得定义 
     * @param i 
     * @param n 
     */  
    public static void adjust(List<Integer> heap,int i, int n) {  
       
        int child;  
        for (; i <= n / 2; ) {  
            child = i * 2;  
            if(child+1<=n&&heap.get(child)<heap.get(child+1))  
                child+=1;/*使child指向值较大的孩子*/  
            if(heap.get(i)< heap.get(child)){  
                swap(heap,i, child);  
                /*交换后,以child为根的子树不一定满足堆定义,所以从child处开始调整*/  
                i = child;  
               
            }  else break;
        }  
    }  
  
   //对一个最大堆heap排序
    public static void heapSort(List<Integer> heap) {  
       
        for (int i = heap.size()-1; i > 0; i--) {  
        /*把根节点跟最后一个元素交换位置,调整剩下的n-1个节点,即可排好序*/  
            swap(heap,1, i);  
            adjust(heap,1, i - 1);  
        }  
    }  
   public static void main(String args[]) { 
        List<Integer> array = new ArrayList<Integer>(Arrays.asList(null, 
1, 2, 5, 10, 3, 7, 11, 15, 17, 20, 9, 15, 8, 16));
        adjust(array);//调整使array成为最大堆
       
        delete(array,8);//堆中删除下标是8的元素
        System.out.println("删除后");
        print(array);
        insert(array, 99);//堆中插入
        print(array); 
        heapSort(array);//排序
        System.out.println("将堆排序后:");
        print(array);
        System.out.println("-------------------------");
        List<Integer> array1=new ArrayList<Integer>();
        insert(array1,0);
        insert(array1, 1);insert(array1, 2);insert(array1, 5);
        insert(array1, 10);insert(array1, 3);insert(array1, 7);
        insert(array1, 11);insert(array1, 15); insert(array1, 17);
        insert(array1, 20);insert(array1, 9);
        insert(array1, 15);insert(array1, 8);insert(array1, 16);
        print(array1);
        
        System.out.println("==============================");
        array=new ArrayList<Integer>(Arrays.asList(null,45,36,18,53,72,30,48,93,15,35));
        adjust(array);
          insert(array, 80);//堆中插入
          print(array);
         delete(array,2);//堆中删除80的元素
         print(array);
         delete(array,2);//堆中删除72的元素
         print(array);
              
    } 
} 


程序运行: 
D:\java>java   Heap 
================================================= 
调整后的初始堆: 
20 17 16 15 9 15 11 1 10 3 2 7 8 5 
删除后 
20 17 16 15 9 15 11 5 10 3 2 7 8 
99 17 20 15 9 15 16 5 10 3 2 7 8 11 
将堆排序后: 
2 3 5 7 8 9 10 11 15 15 16 17 20 99 
------------------------- 
20 17 16 10 15 9 15 0 5 2 11 1 7 3 8 
============================== 
================================================= 
调整后的初始堆: 
93 72 48 53 45 30 18 36 15 35 
93 80 48 53 72 30 18 36 15 35 45 
93 72 48 53 45 30 18 36 15 35 
93 53 48 36 45 30 18 35 15 
好了,想必大家都明白了,下一篇文章将放出相关算法及结果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【算法】堆,最大堆(大顶堆)及最小堆(小顶堆)的实现 的相关文章

  • 算法和数据结构的学习之路

    推荐网站 LeetCode 牛客网 Visualgo net 推荐入门书籍 小灰算法 1 入门基础算法知识 2 面试常见算法题
  • python 生成巨大的excel表格xlsxwriter

    原来我是用xlwt来生成excel的 生成的后缀名为xls 但是由于数据太多于是报了个 ValueError row index 65536 not an int in range 65536 错误 原因是 在xlwt中生成的xls文件最多
  • Maven 项目之pom.xml 提示Unknow Error

    今天学习如何搭建SpringCloud 基础项目 pom xml 文件提示Unknow Error 异常 尝试解决办法 我更想maven 项目依赖 检查maven 项目所依赖的jar 包是否正常下载到本地仓库 但都没有解决该问题 经过goo
  • Oracle Data Pump 使用expbp 和 impdp 导出和导入

    预备 创建dmp文件存放文件夹 不创建后面会发生错误 mkdir p opt oracle dmp 1 创建directory数据库对象并授权 sqlplus as sysdba SQL gt create or replace direc
  • Basic Level 1046 划拳 (15分)

    题目 划拳是古老中国酒文化的一个有趣的组成部分 酒桌上两人划拳的方法为 每人口中喊出一个数字 同时用手比划出一个数字 如果谁比划出的数字正好等于两人喊出的数字之和 谁就赢了 输家罚一杯酒 两人同赢或两人同输则继续下一轮 直到唯一的赢家出现
  • 算法推荐技术合规要点梳理与备案指引

    2022年3月1日 国家互联网信息办公室 工业和信息化部 公安部以及国家市场监督管理总局联合发布的 互联网信息服务算法推荐管理规定 以下简称 规定 正式生效 同日 互联网信息服务算法备案系统正式上线运行 下文将简述算法推荐技术合规要点以及备
  • vue3中使用el-table-column sortable对数据进行排序-如何将用户的选择回显到table上显示状态

    element plus 当通过其他设置改变了排序条件后 显示表格需要对应改变筛选状态 在模板中 使用sortable属性将表格列设置为可排序 并绑定一个变量来保存排序的状态
  • 精通python100天——第一天:初识python及环境安装

    课程的初衷 为了小伙伴们 能系统性的从入门到精通python的主要技术点 深入浅出 结合实例 结合实际公司级的项目 让学完这套课程的小伙伴能直接用到工作中去 或达到求职的水平 Python简介 Python是由荷兰人吉多 范罗苏姆 Guid
  • 基于Java语言构建区块链(二)—— 工作量证明

    最终内容请以原文为准 https wangwei one posts 7890ab7e html 引言 上一篇文章中 我们实现了区块链最基本的数据结构模型 添加区块以及和前一个区块连接在一起 但是 我们的实现方式非常简单 而真实的比特币区块
  • 小程序性能优化之页面预加载方案——让你的小程序运行如飞 集成篇

    小程序性能优化之页面预加载方案 集成篇 转载请注明出处 https blog csdn net sinat 27612147 article details 80802725 前言 之前看到一篇文章 微信小程序之提高应用速度小技巧 是讲如何
  • Python基础复习总结

    文章目录 Python基础复习 Python的下载与安装 标识符 关键字 模块 条件 循环语句 if elif else for循环 while循环 成员测试 Python中的数据类型 序列 列表 list 元组 tuple 集合 set
  • javascript数据类型number、string和布尔

    number数字类型 计算机number是有一个范围的 2的53次方 2的53次方 注意书写顺序 例如一个商品17 45 买3个打9折 以下两种写法保留两位小数结果是不相同的 var obj age 20 var num 17 45 con
  • 8-使用QT5的鼠标事件和滚轮事件

    使用QT5的鼠标事件和滚轮事件 完成鼠标左键拖动窗口 双击全屏 滚轮放大缩小窗口大小 这里使用的是QMouseEvent类里面的鼠标事件 通常进行重定义部件的鼠标事件处理函数来实现自定义的内容操作 同样 鼠标滚轮操作是利用QWheelEve
  • 三个可替代“迅雷”的下载软件,速度超快!

    今天推荐可以替代迅雷的软件 那些你使用迅雷无法下载的资源 现在都可以下载了哦 1 qBittorrent 解压提供的安装包 然后双击 qbittorrent exe 找到你要下载的磁力链接 点击右上角 添加下载任务 设置你的下载路径 点击
  • K8S控制器Deployment

    简述 Deployment为Pod和ReplicaSet提供了一个声明式定义 declarative 方法 用来替代以前的ReplicationController来方便的管理应用 典型的应用场景包括 定义Deployment来创建Pod和
  • 关于搭建测试环境(详细)

    简述搭建测试环境 本人呢 是一名测试人员 以前工作的时候我们的测试环境都是网管 运维 帮我们管理的 顶多也就在tomcat下部署项目包 还是操作几个比较简单的指令 前不久就自己搭了套测试环境 然后也没事总结了一下 大致相同 可能存在个别差异
  • k8s lifecycle——poststart和prestop

    1 lifecycle的声明 lifecycle postStart exec command bin sh c sleep 100 preStop exec command bin sh c sleep 100 2 poststart 容
  • Nginx修改文件配置--配置本地网址

  • seata-server-1.5.2的环境搭建

    配置文件位置 使用的是nacos和mysql数据库 简单部署在Win10上 Linux上配置修改相同 启动命令不同 找到 seata server 1 5 2 seata conf目录下的application yml和applicatio
  • win10 vscode+clangd代码提示+cmake+mingw编译器和调试器

    win10 vscode clangd代码提示 cmake mingw编译器和调试器 前言 第一步 把cmake mingw llvm win64安装好 安装好vscode必备的插件 利用cmake构建一个项目 利用vscode的launc

随机推荐

  • 移动端VUE实现一周课程表

    效果图 点击课程弹出课程详情 代码 使用嵌套的v for循环去实现
  • m3u8文件中的 m3u8标签与属性说明

    EXTM3U 每个M3U文件第一行必须是这个tag 请标示作用 EXT X VERSION 3 该属性可以没有 EXT X MEDIA SEQUENCE 140651513 每一个media URI在PlayList中只有唯一的序号 相邻之
  • ubuntu18.04安装cuda、cudnn、pytorch-gpu

    cuda安装 参考博客 https blog csdn net mbdong article details 121926316 https mp weixin qq com s ZTzfC7xp8PVMvOONVIiK6g https b
  • Vue简单实例——Vuex代码实现

    简单介绍 上一篇我们介绍了Vuex的理论 这一章我们开始说明Vuex在代码方面的实现 基本使用 要想使用Vuex首先要进行下载 在下载的时候需要注意 如果你使用的vue2的框架 需要使用vuex的3版本 如果使用的是vue3的框架 才可以使
  • Open3D DbScanClustering聚类算法及聚类分簇可视化及存储

    DBSCAN聚类算法 是基于密度的聚类算法 该算法需要两个参数 labels np array pcd cluster dbscan eps 0 02 min points 10 print progress True 入参 eps 定义到
  • Java实体类与byte数组相互转换

    1 使用ByteArrayStream 和 ObjectStream public abstract class ByteConvert public byte getByte try ByteArrayOutputStream out n
  • Qt技巧:sqlite数据库 判断表是否存在

    m dbTest QSqlDatabase addDatabase QSQLITE m dbTest setDatabaseName sqlite db if m dbTest open qDebug lt lt database succ
  • Android安卓期末大作业 新闻app 实现注册登录增删改查功能

    Android安卓期末大作业 新闻app 文末附下载链接 app情况如下图所示 点我下载 https download csdn net download weixin 43474701 75953692
  • 泛微oa明细表添加按钮_关于E8,这些快捷方式你必须知道

    摘要 快捷方式不只是快 更能带来酣畅用户体验 本期场景为您带来E8快捷方式精选 看着那些大神们手指翻飞 在键盘上灵活起舞 说实话 你有过几分羡慕吗 快捷输入这东西 有时候真是少不了 虽然只是几秒几十秒的差异 但用户体验着实不同 试想 当你正
  • 基于OpenCV的数码管数字识别

    利用OpenCV可实现工业仪表设备的读数识别 仪表一般可分为两 数字式仪表和指针式仪表 本博文主要介绍一下数字式仪表识别的关键技术 下图是用软件模拟的数码管图片 本文识别的也就是图中的数字 一 图像定位 在实际的应用场景中 拍摄到的仪表区域
  • SparkStreaming与Kafka010之05之01 Consumer

    package Kafka010 import Kafka010 Utils MyKafkaUtils import org apache kafka clients consumer ConsumerRecord import org a
  • Java的Timer定时任务的一个小Demo

    今天遇到一个需求 需要读取数据库的地址 返回地址的经纬度和所属区县 但是由于数据库的地址信息会没有或者错误 那么我的循环就会停止 于是想到写一个定时任务来解决这个问题 下面是定时任务的一个小Demo 希望可以帮到需要的人 package e
  • c#基础知识---集合之点阵列(BitArray)

    BitArray 类管理一个紧凑型的位值数组 它使用布尔值来表示 其中 true 表示位是开启的 1 false 表示位是关闭的 0 当您需要存储位 但是事先不知道位数时 则使用点阵列 您可以使用整型索引从点阵列集合中访问各项 索引从零开始
  • 吉林大学软件学院计网复习知识点

    吉林大学软件学院计网复习知识点 目录 前言 单项选择题知识点 填空题知识点 名词解释题知识点 简答题知识点 应用题知识点 课后习题答案 尾声 前言 大家好 我是星辉 以上便是根据我手头的资料整理的 希望能够对大家有些许的帮助 目前分为两部分
  • java对象引用改变地址_Java 使用调用方法改变了对象的地址后,主函数中输出结果不变...

    今天看引用传递 值传递相关的东西 说到String的值自初始化后不能修改 我就想 如果调用函数改变了String类对象的引用 那主函数里头的输出结果会不会变化 结果发现不行 同样的 今天看引用传递 值传递相关的东西 说到String的值自初
  • 力扣二叉树--对称二叉树,从上向下打印二叉树刷题

    给你一个二叉树的根节点 root 检查它是否轴对称 示例 1 输入 root 1 2 2 3 4 4 3 输出 true 示例 2 输入 root 1 2 2 null 3 null 3 输出 false 查询对称二叉树 主要用途在于判断一
  • 活跃性(Liveness)

    一个并发应用能够及时执行任务的特性称为活跃性 这一节讲述最常见的一种活跃性问题 死锁 并将简单的介绍另外两种活跃性问题 分别为饥饿和活锁 死锁 Deadlock 死锁描述的是这样一种情景 当两个或者多个线程处于永远阻塞状态 并等待对方 如下
  • (工具)JavaScript 金额转大写

    function moneyToUpCase money if money return if typeof money number money money money money replace g 替换originalVal中的 mo
  • 利用非对称PWM模式体验编码器功能

    通常在STM32芯片的通用TIMER或高级TIMER都带编码器功能 支持基于1路或2路输入的编码脉冲计数 我们一般外接正交编码器 使用2路输入 TIMER硬件基于2路输入的相差特征来确定计数方向并依据方向对计数器做递增或递减操作 正交编码器
  • 【算法】堆,最大堆(大顶堆)及最小堆(小顶堆)的实现

    此坑待埋 点击打开漫谈经典排序算法 一 从简单选择排序到堆排序的深度解析链接 白话经典算法系列之七 堆与堆排序 二叉排序树与二叉堆 堆排序 注 这篇文章说明了如何从一个数组构建一个最大堆 推荐看 最大堆的插入 删除 调整 排序操作 图解 程