堆排序

堆排序

Dart实现堆排序

思想

利用堆(heap)这种数据结构来进行排序

堆需要满足两个条件

  • 完全二叉树
  • 子节点的值总是小于或者大于它的父节点
规整某个节点 heapify
/**
 * tree
 * i 要规整的节点
 * n 节点总数
 */
heapify(List tree, int i, int n) {
  //保证节点i与他的子节点符合堆定义 即节点i的值在他和他的子节点中是最大的
  int c1 = i * 2 + 1; //节点i的理论左子节点
  int c2 = i * 2 + 2; //节点i的理论右子节点
  int max = i;
  if (c1 < n && tree[c1] > tree[max]) {
    max = c1;
  }
  if (c2 < n && tree[c2] > tree[max]) {
    max = c2;
  }
  //不满足堆定义,交换父节点和子节点中较大的那个,并对交换后的子节点进行规整
  if (max != i) {
    swap(tree, i, max);
    heapify(tree, max, n);
  }
}

swap(List tree, int i, int max) {
  int temp = tree[i];
  tree[i] = tree[max];
  tree[max] = temp;
}
无序数列构建堆
/**
 *  堆中某节点的子父节点的下标
 *  int child1 = i*2+1;//节点i的理论左子节点
 *  int child2 = i*2+2;//节点i的理论右子节点
 *  int parent = (i-1)~/2;//节点i的父节点
 */
buildHeap(List tree) {
  int n = tree.length;
  //找到最后一个节点的父节点 最后一个节点是n-1 ,父节点为((n-1)-1)/2 即n/2-1
  for (int i = n ~/ 2 - 1; i >= 0; i--) {
    heapify(tree, i, n);
  }
}

堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

大顶堆:每个结点的值都大于它的左右子结点的值,升序排序用大顶堆。

小顶堆:每个结点的值都小于它的左右子结点的值,降序排序用小顶堆。

排序流程

1.从原始数据集构建堆 - 从最后一个节点(n-1)的父节点(i-1)/2开始递减做heapify
2.把堆首和堆尾节点互换并摘除最末尾节点
3.堆大小-1并对堆首元素heapify
4.重复2,3步骤直到堆大小为1

Dart实现
main() {
  var test = [4, 5, 6, 29, 3, 1, 7, 9];
  heapSort(test);
  print(test);//输出结果为[1, 3, 4, 5, 6, 7, 9, 29]
}

heapSort(List tree) {
  int n = tree.length;
  //构建堆
  buildHeap(tree);
  //从最后一个节点开始 交换堆首和堆尾节点互换
  for (int i = n - 1; i >= 0; i--) {
    swap(tree, 0, i);
    //规整堆首节点 并将堆规模-1
    heapify(tree, 0, i);
  }
}
/**
 *  堆中某节点的子父节点的下标
 *  int c1 = i*2+1;//节点i的理论左子节点
 *  int c2 = i*2+2;//节点i的理论右子节点
 *  int parent = (i-1)~/2;//节点i的父节点
 */
buildHeap(List tree) {
  int n = tree.length;
  //找到最后一个节点的父节点 以此开始直至堆首 规整每个节点 最后一个节点是n-1 ,父节点为((n-1)-1)/2 即n/2-1
  for (int i = n ~/ 2 - 1; i >= 0; i--) {
    heapify(tree, i, n);
  }
}


/**
 * tree
 * i 要规整的节点
 * n 节点总数
 */
heapify(List tree, int i, int n) {
  //保证节点i与他的子节点符合堆定义 即节点i的值是最大的
  int c1 = i * 2 + 1; //节点i的理论左子节点
  int c2 = i * 2 + 2; //节点i的理论右子节点
  int max = i;
  if (c1 < n && tree[c1] > tree[max]) {
    max = c1;
  }
  if (c2 < n && tree[c2] > tree[max]) {
    max = c2;
  }
  if (max != i) {
    swap(tree, i, max);
    heapify(tree, max, n);
  }
}

swap(List tree, int i, int max) {
  int temp = tree[i];
  tree[i] = tree[max];
  tree[max] = temp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值