0%

20191106记录

堆、判断2的幂次方、Python线程安全

Python的线程安全

什么是线程安全?

在一段程序中,如果两个线程t1,t2共享一个全局变量,且这多个线程对同一个全局变量操作会出现资源竞争的问题,从而导致结果会不正确,即遇到线程安全的问题。所以一般采用线程同步或互斥锁机制保证共享数据在任何时刻,最多有一个线程访问,以保证数据的正确性。

其中Python内置类型: ditc, list, tuple是线程安全的。

参考

快速判断一个数是否是 2 的幂次方

如果将这个数减去1后会发现,仅有的那个1会变为0,而原来的那n个0会变为1;因此将原来的数与去减去1后的数字进行与运算后会发现为零。
例如:

则8(1000)就是2的幂次方。

参考

来源

堆是一种 非线性结构 ,可以把堆看作一个数组,也可以被看作是一个 完全二叉树 (若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。), 堆其实就是 利用完全二叉树的结构来维护的一维数组。

大顶堆: 每个节点的值都 大于或等于 其左右孩子节点的值;

小顶堆: 每个节点的值都 小于或等于 其左右孩子节点的值;

堆的这种特性非常有用,常常被当作 优先队列 使用,因为可以快速的访问到“最重要”的元素。

堆特点:

对堆中的节点按层进行编号,映射到数组中:

所以有如下堆的定义:

大顶堆:

小定顶堆:

堆排序的过程:

基本思想:

  1. 将待排序序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点。
  2. 将其与末尾元素进行交换,此时末尾就为最大值。
  3. 然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。
  4. 如此反复执行,便能得到一个有序序列了,建立最大堆时是从 最后一个非叶子节点 开始从下往上调整的。

升序 — 大顶堆;
降序 — 小顶堆;

具体步骤:

步骤一: 构造初始堆,将给定的无序序列构造成一个大顶堆:

  1. 给定无序序列如下:

  1. 从最后一个非叶子节点(arr.length/2 -1 = 5/2-1 = 1,也就是下面的 6 节点),从左至右,从下往上进行调整:

节点6先和其左孩子比较a[2 * 1 + 1] = arr[3] =5 ,因为6 > 5所以不作调整;
和其右孩子比较a[2 * 1 + 2] = arr[4] =9, 因为 9 > 6 ,所以两者进行交换

  1. 找到下一个非叶子节点,当前坐标-1即 1-1 = 0,即第二个非叶子节点为4, [4,9,8]中9元素最大, 4和9 交换:

  1. 这时,交换导致了子根[4,5,6]混乱,继续调整,[4,5,6]中 6 最大,交换 4 和6:

步骤二:将堆顶元素和末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换:

  1. 将堆顶元素9 和末尾元素4 进行交换:

  1. 重新调整结构,使其继续满足堆定义:

  1. 再将堆顶元素 8 与末尾元素 5 进行交换,得到第二大元素8:

  1. 后续过程,继续进行调整、交换,如此反复,最终使得整个序列有序:

代码: