当前位置: 首页 > wzjs >正文

重庆网站设计总部营销型外贸网站建设

重庆网站设计总部,营销型外贸网站建设,不锈钢餐具做外贸哪个网站好,公司的创建一、概念 之前在队列的时候讲过,队列是先进先出的,是根据你的插入顺序来确定优先级的。 而有时候我们希望可以通过元素内容来确定优先级。 比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话&am…

一、概念

之前在队列的时候讲过,队列是先进先出的,是根据你的插入顺序来确定优先级的。

而有时候我们希望可以通过元素内容来确定优先级。

比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位时可能会让成绩好的同学先挑座位。
在这种情况下, 数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象 。这种数据结构就是优先级队列 (Priority Queue)

 堆的性质:

  • 堆总是一棵完全二叉树。
  • 堆中某个节点的值总是不大于或不小于其父节点的值。如果是某个节点值大于左右结点就是大根堆如果是某个节点值小于左右结点,就是小根堆

二、堆的底层结构

堆实际上是二叉树的顺序存储,就是用数组的方式,来表示二叉树。

小根堆:

而且我们可以发现,数组中的存储顺序是层序遍历的结果

大根堆:

从堆的概念可知,堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储

如果不是完全二叉树:

中间就会浪费许多空间,所以并不是一个好的选择

如果是一个完全二叉树:

不仅不会浪费空间,我们还可以利用完全二叉树的一些公式:

  • 如果i0,则i表示的节点为根节点,否则i节点的父亲节点为 (i - 1)/2
  • 如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子
  • 如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子

三、堆的实现和创建

我们一边写代码一边进行画图介绍

首先创建一个堆类,指定堆初始大小为10,可以传入数组:

public class MyHeap {//存放数组元素private int[] elem;//记录有效数据个数private int usedSize;//初始化为10public MyHeap() {elem = new int[10];}//初始化public void init(int[] array) {for (int i = 0; i < elem.length && i < array.length; i++) {elem[i] = array[i];usedSize++;}}
}

1.将数据转化为堆的存储

那么我们如何把数组转化为,表示堆的逻辑呢?

我们要将现在的这串数据转化为堆,相信大家想到的是通过逆序排序就直接Ok了。

那我问你

所以单纯的逆序排序是不太ok的

正确的排序方式:

我们现在就可以写一部分代码了:

    public void createHeap() {for (int parent = (usedSize-1-1) / 2; parent >= 0; parent--) {//用来调整siftDown();}}private void siftDown() {}

继续之前的操作:

最终代码实现:

    public void createHeap() {for (int parent = (usedSize-1-1) / 2; parent >= 0; parent--) {//用来调整siftDown(parent,usedSize);}}private void siftDown(int parent, int end) {//假设左孩子是最大值//通过 i * 2 + 1 = 左子树int child = (parent * 2) + 1;//孩子节点越界就说明结束了while (child < end) {//右孩子没有越界的情况     左孩子       <    右孩子 吗?if (child + 1 < end && elem[child] < elem[child+1]) {//右孩子比左孩子大child++;}//孩子节点大于父亲节点if (elem[child] > elem[parent]) {swap(parent,child);parent = child;child = (child * 2) + 1;}else {//说明不需要调整了break;}}}private void swap(int i, int j) {int tmp = elem[i];elem[i] = elem[j];elem[j] = tmp;}

那么来测试一下:

    public static void main(String[] args) {int [] array = {27,15,19,18,28,34,65,49,25,37};MyHeap myHeap = new MyHeap();myHeap.init(array);myHeap.createHeap();}

结果:

2.在堆中添加数据

由于我们本质是通过数组存储的,所以还是会存在数组满的情况,那就需要判断一下是不是满了,满了就扩容。

那我们就当是已经解决了长度不够的问题:

代码:

    public void offer(int val) {if (isFull()) {elem = Arrays.copyOf(elem,elem.length * 2);}elem[usedSize] = val;usedSize++;siftUp(usedSize-1);}private void siftUp(int child) {//计算父亲节点位置int parent = (child - 1) / 2;while (parent >= 0) {if (elem[parent] < elem[child]) {swap(parent,child);child = parent;parent = (child - 1) / 2;}else {break;}}}

测试:

    public static void main(String[] args) {int [] array = {27,15,19,18,28,34,65,49,25,37};MyHeap myHeap = new MyHeap();myHeap.init(array);myHeap.createHeap();myHeap.offer(70);}

结果:

 如果我们直接通过offer方法来创建堆呢?是不是每一次都是堆,测试一下:

    public static void main(String[] args) {MyHeap myHeap = new MyHeap();myHeap.offer(27);myHeap.offer(15);myHeap.offer(19);myHeap.offer(18);myHeap.offer(28);myHeap.offer(34);myHeap.offer(65);myHeap.offer(49);myHeap.offer(25);myHeap.offer(37);}

根据结果看虽然顺序会有不同,但是仍然是满足大根堆条件的。

3.堆中删除数据

 代码实现:

    public int poll() {//判断是否为nullif (isEmpty()) {return -1;}int old = elem[0];//交换后逻辑删除swap(0,usedSize-1);usedSize--;//向下调整siftDown(0,usedSize);return old;}private boolean isEmpty() {return usedSize == 0;}

四、PriorityQueue

1.特性

Java 集合框架中提供了 PriorityQueue PriorityBlockingQueue 两种类型的优先级队列, PriorityQueue 是线 程不安全的, PriorityBlockingQueue 是线程安全的 ,本文主要介绍 PriorityQueue

关于PriorityQueue的使用要注意:

  1. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常
  2. 不能插入null对象,否则会抛出NullPointerException
  3. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容(理论上的,实际肯定是不可以无限插入的)
  4. 插入和删除元素的时间复杂度为O(log2N)
  5. PriorityQueue底层使用了堆数据结构
  6. PriorityQueue默认情况下是小堆---即每次获取到的元素都是最小的元素
  7. 使用时必须导入PriorityQueue所在的包,即:
import java.util.PriorityQueue;

2.常用方法函数名

函数名功能介绍
boolean offer(E e)
插入元素 e ,插入成功返回 true ,如果 e 对象为空,抛出 NullPointerException 异常,时
间复杂度,注意:空间不够时候会进行扩容
E peek()
获取优先级最高的元素,如果优先级队列为空,返回 null
E poll()
移除优先级最高的元素并返回,如果优先级队列为空,返回 null
int size() 
获取有效元素的个数
void clear()
清空
boolean isEmpty()
检测优先级队列是否为空,空返回 true

    public static void main(String[] args) {PriorityQueue<Integer> queue = new PriorityQueue<>();//判断是否为nullSystem.out.println(queue.isEmpty());//入堆queue.offer(21);queue.offer(56);queue.offer(44);queue.offer(23);//看一下堆顶元素System.out.println(queue.peek());//返回堆顶元素并退出System.out.println(queue.poll());System.out.println(queue.poll());//返回堆中元素个数System.out.println(queue.size());//清控堆中元素queue.clear();//再次判断是否为nullSystem.out.println(queue.isEmpty());}

 结果:

3.PriorityQueue的构造方法

构造函数功能介绍
PriortiyQueue()创建一个空的优先级队列,默认容量是11
PriortiyQueue(int initialCapacity)
创建一个初始容量为 initialCapacity 的优先级队列,注意:initialCapacity不能小于 1 ,否则会抛 IllegalArgumentException 异 常
PriortiyQueue(Collection<? extends E> c)用一个集合来创建优先级队列

它们多数都调用了,有两个参数的构造方法。这两个参数的构造方法,给了一个比较器,你可以通过这个比较器来控制大根堆或小根堆。(两个参数的构造方法后面再做介绍他的作用)

3.1 参数为 Collection<? extends E> c 的构造方法

意思是只要实现了Collection的数据结构都可以转换为堆:

    public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(23);list.add(34);list.add(45);list.add(56);list.add(67);list.add(78);//将链表PriorityQueue<Integer> queue = new PriorityQueue<>(list);System.out.println(queue.toString());}

 结构:

3.2 通过Comparator实现大根堆小根堆的控制

有这样一个构造方法,传入构造器就可以对控制元素的比较:

我们需要创建一个比较器:

class IntCmp implements Comparator<Integer> {//大根堆写法@Overridepublic int compare(Integer o1, Integer o2) {return o2.compareTo(o1);}//小根堆写法
//    @Override
//    public int compare(Integer o1, Integer o2) {
//        return o1.compareTo(o2);
//    }
}

 测试一下:

    public static void main(String[] args) {PriorityQueue<Integer> queue = new PriorityQueue<>(new IntCmp());queue.offer(23);queue.offer(34);queue.offer(45);queue.offer(56);queue.offer(67);queue.offer(78);System.out.println(queue.toString());}

那代码是如何实现的呢?我们来看一下

大家可能compare和compareTo看懵了,我们来查看一下Integer里面实现的:

 如果是我们自己的类如何比较呢?

我们有这样一个学生类:

class Student {public int age;public Student(int val) {age = val;}
}
    public static void main(String[] args) {PriorityQueue<Student> queue = new PriorityQueue<>();queue.offer(new Student(9));queue.offer(new Student(12));queue.offer(new Student(45));queue.offer(new Student(43));}

我们并没有指定Student的比较方式,这是不被允许的

那我们就就处理一下:

class Student implements Comparable<Student>{public int age;public Student(int val) {age = val;}@Overridepublic int compareTo(Student o) {return this.age - o.age;}@Overridepublic String toString() {return age + " ";}
}
class IntCmp implements Comparator<Student> {//大根堆写法@Overridepublic int compare(Student o1, Student o2) {//这里去调用Student的compareToreturn o2.compareTo(o1);}//小根堆写法
//    @Override
//    public int compare(Student o1, Student o2) {
//        return o1.compareTo(o2);
//    }
}

测试:

        public static void main(String[] args) {PriorityQueue<Student> queue = new PriorityQueue<>(new IntCmp());queue.offer(new Student(9));queue.offer(new Student(12));queue.offer(new Student(45));queue.offer(new Student(43));System.out.println(queue.toString());}

五、堆排序

经过上面这么多图的讲解,我们现在就知道了,如果是大根堆,堆顶元素一定是最大值,反之就是最小值。那我们就可以像删除元素那样,把最后第一个元素和最后一个元素交换再进行操作保证仍然是堆,那么现在堆底元素就是最大值。下一次堆顶元素就是第二大的值了,以此类推。

图解:

 代码:

    /*** 堆排序* 时间复杂度:O(log2n * n)* 空间复杂度:O(N)* 稳定性:不稳定*/public void heapSort(int[] array) {//先调整为大根堆createHeap(array);//end控制未排序数据的末尾int end = array.length - 1;while (end >= 0) {//交换堆首和堆尾元素swap(array,0,end);//向下调整siftDown(array,0,end);//有效数据已经放到末尾end--;}}private void createHeap(int[] array) {for (int parent = (array.length-1-1) / 2; parent >= 0; parent--) {//用来调整siftDown(array,parent,array.length);}}private void siftDown(int[] array, int parent, int end) {//假设左孩子是最大值//通过 i * 2 + 1 = 左子树int child = (parent * 2) + 1;//孩子节点越界就说明结束了while (child < end) {//右孩子没有越界的情况     左孩子       <    右孩子 吗?if (child + 1 < end && array[child] < array[child+1]) {//右孩子比左孩子大child++;}//孩子节点大于父亲节点if (array[child] > array[parent]) {swap(array,parent,child);parent = child;child = (child * 2) + 1;}else {//说明不需要调整了break;}}}private void swap(int[] array, int i, int j) {int tmp = array[i];array[i] = array[j];array[j] = tmp;}

测试:

    public static void main(String[] args) {MyHeap heap = new MyHeap();int[] array = {27,15,19,18,28,34,65,49,25,37};heap.heapSort(array);}

http://www.dtcms.com/wzjs/315216.html

相关文章:

  • 用dreamever如何建设网站百度一下官网网址
  • 表格布局的网站北京外包seo公司
  • 电子商务网站建设专业主修课程搜索引擎有哪些分类
  • 外包做的网站 需要要源代码吗最常用的网页制作软件
  • 柳市做公司网站电脑培训学校排名
  • 网站制作资质网店代运营诈骗
  • 空调维修技术支持东莞网站建设app拉新平台哪个好佣金高
  • 买奢侈品代工厂做的产品的网站百度首页的ip地址
  • 晋江网站建设晋江如何网页优化
  • 江西医疗网站备案前置审批福州seo公司排名
  • 软件行业发展前景百度seo搜索引擎优化培训
  • java做网站访问量并发关键路径
  • 东莞优秀网站建设企业网站建设哪家好
  • 东莞网站建设公司口碑排名个人如何建立免费网站
  • 网站设计_网站建设_手机网站建设今天的新闻内容
  • 商务网站建设步骤有几个头条搜索
  • 包头做网站哪家好无线新闻台直播app下载
  • 做网站建设的电销教育机构加盟
  • 浙江省建设厅网站高工北京网站优化企业
  • 发票商品名称网站建设下载百度导航app
  • 泉州哪里做网站开发武汉seo服务外包
  • 成品网站建设哪家好网络营销专业大学排名
  • 池州网站建设费用吉林网络推广公司
  • 网站菜单代码山东16市最新疫情
  • 楚雄做网站张文宏说上海可能是疫情爆发
  • 南京移动网站设计seo交互论坛
  • 百度文库ai助手网页版内部优化
  • 领地免费网站开发网络推广怎么找客户资源
  • 阿拉尔市建设局网站百度pc网页版
  • 网站营销单页面留言抖音权重查询