堆栈

来源:互联网 发布:python 多进程写文件 编辑:程序博客网 时间:2024/05/18 21:50

堆栈只能在一端(栈顶(top))对数据项进行插入和删除,堆:先进后出,栈:后进先出

操作系统:

栈:是由编译器自动分配释放,存放函数的参数值,局部变量的值等,调用完毕立即释放,使用的是一级缓存

堆:存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定

数据结构:

堆:可以被看成是一棵树,如:堆排序

栈:一种后进先出的数据结构

java自动管理栈和堆

栈的优势是存取速度比堆快,仅次于直接位于CPU中的寄存器,缺点:存在栈中的数据大小与生存期必须确定,缺乏灵活性。栈数据可以共享

堆的优势是可以动态地分配内存大小,JAVA的垃圾收集器会自动收走不再使用的数据,缺点:由于要在运行时动态分配内存,存取速度较慢。

包装类数据全部存在堆中

例:

int a = 3;

int b = 3;

编译器先处理int a= 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b= 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。

数据结构 堆:

什么是堆

堆是一种特殊的二叉完全树。堆的一个主要特点是它以一定的偏序(a partial order)来保存所有节点[译者注:此处的偏序是指不完全的排序,堆只需要满足父节点大于两个子节点,而子节点之间没有要求]。作为一颗完全树,一层中的节点是从左到右填满的。如果一个节点没有左儿子,那么它一定没有右儿子。并且在第h层中如果存在节点,那么第h-1层必须是填满的。

 

以下是堆的正式定义(摘自Computer Algorithms by S. Baase and A. Van Gelder):

 

一个二叉树V是一个堆,当且仅当它满足以下条件:

  • V从根节点至h-1层是完全树
  • 所有的叶子节点只存在于h与h-1层上
  • 所有到达h层叶子节点的路劲都在到达h-1层叶子节点路径的左侧

堆有两种:最大堆和最小堆。最小堆中每个节点的优先级小于或者等于它的子节点;最大堆则相反,每个节点的优先级都大于或者等于它的子节点。

 

图示最大堆(左)和最小堆(右):

经典排序算法 - 堆排序Heap sort

堆排序有点小复杂,分成三块

第一块,什么是堆,什么是最大堆

第二块,怎么将堆调整为最大堆,这部分是重点

第三块,堆排序介绍


第一块,什么是堆,什么是最大堆

什么是堆

这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。

堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.

数组与堆之间的关系

Heap1

二叉堆一般分为两种:最大堆和最小堆。

什么是最大堆

堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆

因此,最大堆中的最大元素值出现在根结点(堆顶)

节点与数组索引关系

对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约

Image(2)

第二块,怎么将堆调整为最大堆,这部分是重点

整个过程如下图所示

在4,14,7这个小堆里边,父节点4小于左孩子14,所以两者交换

在4,2,8这个小堆里边,父节点4小于右孩子8,所以两者交换

Heap3

上图展示了一趟调整的过程,这个过程递归实现,直到调整为最大堆为止

第三块,堆排序介绍

堆排序就是把堆顶的最大数取出,

将剩余的堆继续调整为最大堆,具体过程在第二块有介绍,以递归实现

剩余部分调整为最大堆后,再次将堆顶的最大数取出,再将剩余部分调整为最大堆,这个过程持续到剩余数只有一个时结束

下边三张图详细描述了整个过程

Heap4

Heap5

Heap6 

参考文章

http://blog.kingsamchen.com/archives/547#viewSource

堆排序:取出根部最大(最小)的元素放入一个数组后,将根的最后一个元素填充到根部,然后重建最大(最小)堆,然后就递归


package com.algorithm;public class HeapSort {public static void main(String[] args) {          // 数组0下标元素作为暂存单元          /*int[] array = { 0, 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5,                 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51 };*/          int[] array = { 0, 49, 38, 65, 97, 76, 13, 27, 49 };            heapSort(array);          for (int i = 1; i < array.length; i++) {              System.out.print(array[i] + " ");          }      }        // 排序函数=====================================================      public static void heapSort(int[] array) {          // 对数组进行筛选,建成一个大顶堆          double len = array.length - 1;          for (int i = (int) Math.floor(len / 2); i > 0; i--) {              heapAdjust(array, i, array.length - 1);          }          for (int i = array.length - 1; i > 1; i--) {              // 将堆顶元素与最后一个元素调换位置,即输出最大值              swap(array, 1, i);              // 将最后一位剔出,数组最大下标变为i-1。自队顶至叶子进行调整,形成一个新堆,此过程称为筛选              heapAdjust(array, 1, i - 1);          }      }        // 建堆函数,认为【s,m】中只有 s      // 对应的关键字未满足大顶堆定义,通过调整使【s,m】成为大顶堆=====================================================      public static void heapAdjust(int[] array, int s, int m) {          // 用0下标元素作为暂存单元          array[0] = array[s];          // 沿孩子较大的结点向下筛选          for (int j = 2 * s; j <= m; j*=2) {              // 保证j为较大孩子结点的下标,j < m 保证 j+1 <= m ,不越界  (此数组真正从1开始固左子树为leftChild=2*s)            if (j < m && array[j] < array[j + 1]) {                  j++;              }              if (!(array[0] < array[j])) {                  break;              }              // 若S位较小,应将较大孩子上移              array[s] = array[j];              // 较大孩子的值变成S位的较小值,可能引起顶堆的不平衡,故对其所在的堆进行筛选              s = j;          }          // 若S位较大,则值不变;否则,S位向下移动至2*s、4*s、。。。          array[s] = array[0];      }        // 交换函数=====================================================      public static void swap(int[] array, int i, int j) {          int temp;          temp = array[i];          array[i] = array[j];          array[j] = temp;      }  }  



package com.algorithm;import com.test.java.intStringToint;public class HeapSortTest2 {public static void main(String args[]) {int[] array = { 49, 38, 65, 97, 76, 13, 27, 49 };int[] array1 = { 1, 2, 7, 4, 34, 25, 67 };sortHeap(array);for (int i = 0; i < array.length; i++) {System.out.print(array[i] + " ");}sortHeap(array1);for (int i = 0; i < array1.length; i++) {System.out.print(array1[i] + " ");}}public static void sortHeap(int[] arr) {int len = arr.length;for (int i = len / 2; i >= 0; i--) {maxHeap(arr, i, len);}for (int i = len - 1; i > 0; i--) {swap(arr, i, 0);maxHeap(arr, 0, i);}}public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void maxHeap(int[] arr, int index, int heapSize) {int leftIndex = index*2+1;//此数组下标从0开始  固leftIndex=index*+1int rightIndex = index*2+2;int largest = index;if (leftIndex < heapSize && arr[index] < arr[leftIndex]) {largest = leftIndex;}if (rightIndex < heapSize && arr[largest] < arr[rightIndex]) {largest = rightIndex;}if (largest != index) {swap(arr, largest, index);maxHeap(arr, largest, heapSize);}}}



#!bin/usr/pythondef left(index):    return index*2+1def right(index):    return index*2+2def maxHeap(arr,index,heapSize):    leftInd=left(index)    rightInd=right(index)    largest=index    if leftInd<heapSize and arr[index]<arr[leftInd]:        largest=leftInd    if rightInd<heapSize and arr[largest]<arr[rightInd]:        largest=rightInd    if largest != index:        arr[largest],arr[index]=arr[index],arr[largest]        maxHeap(arr,largest,heapSize)def heapSort(arr):    for i in range(len(arr)/2,-1,-1):        maxHeap(arr,i,len(arr))            for i in range(len(arr)-1,0,-1):        arr[0],arr[i]=arr[i],arr[0]        maxHeap(arr,0,i)arr=[1,2,7,4,34,25,67]  heapSort(arr)  print arrarr1=[49,38,65,97,76,13,27,49]heapSort(arr1)print arr1


0 0
原创粉丝点击