赞
踩
堆排序利用堆的性质来对数组进行排序,也就是说它的所有操作都是在数组上进行的,类似于树状数组的形式;并不是通过实际上的二叉树排序。
要实现堆排序,首先需要了解堆排序的原理。
堆中某个结点的值总是不大于其父结点的值(大顶堆:头节点值最大)。
堆中某个结点的值总是不小于其父结点的值(小顶堆:头节点值最小)。
因为是排序算法,所以这里不用二叉树结构实现堆结构,使用数组模拟并将其想象成一棵树:
arr = { 0, 1, 2, 3, 4, 5, 6 };
上图的每个位置分别对应一个数组的元素下标
假设这个堆有序,且每个父节点的值大于等于其子节点(大顶堆):
假如上图是一个数组arr,想要在该数组末尾插入一个数字10,并且变更数组元素的顺序使得堆结构依然成立。
因为 堆中某个结点的值总是不大于或不小于其父结点的值,所以需要将2位置(8)和6位置(10)进行比较,当子节点的数值大于父节点,则该子节点和父节点进行交换,即8 与 10 交换。
完成上个步骤,将需要操作的光标变成位置2(10),继续与其父节点位置0(9)进行比较,若大于其父节点,则交换,否则跳出循环。到这里一个插入操作结束。
代码如下:
- void Swap(int *arr, int x, int y)
- {
- int temp = 0;
- temp = arr[x];
- arr[x] = arr[y];
- arr[y] = temp;
- }
-
- void HeapInsert(int *arr, int index)
- {
- while (arr[index] > arr[(index - 1) / 2])
- {
- //交换函数swap
- Swap(arr, index, (index - 1) / 2);
- index = (index - 1) / 2;
- }
- }

假设对刚才的数组首元素进行变更,那么要如何使该数组保持堆数组
若将首元素替换为7,则需要如何进行变动?
重复该过程,即可得到新数组
代码入下:
- /*
- arr: 目标数组
- index: 目标节点
- size: 数组大小监测
- */
- void HeapIfy(int *arr, int index, int size)
- {
- int left = index * 2 + 1;
- while (left < size)
- {
- //找较大子节点
- int largest = (left + 1 < size && arr[left + 1] > arr[left]) ? left + 1 : left;
-
- //比较子节点和父节点
- if (arr[largest] > arr[index])
- Swap(arr, largest, index);
- else
- break;
-
- //循环结构
- index = largest;
- left = index * 2 + 1;
- }
- }

第一次交换:
排序后:
第二次交换:
依次执行即可实现排序操作。
- #define _CRT_SECURE_NO_WARNINGS 1
- #include <stdio.h>
- #include <windows.h>
-
- void Swap(int *arr, int x, int y)
- {
- int temp = 0;
- temp = arr[x];
- arr[x] = arr[y];
- arr[y] = temp;
- }
-
- void HeapInsert(int *arr, int index)
- {
- while (arr[index] > arr[(index - 1) / 2])
- {
- //交换函数swap
- Swap(arr, index, (index - 1) / 2);
- index = (index - 1) / 2;
- }
- }
-
- /*
- arr: 目标数组
- index: 目标节点
- size: 数组大小监测
- */
- void HeapIfy(int *arr, int index, int size)
- {
- int left = index * 2 + 1;
- while (left < size)
- {
- //找较大子节点
- int largest = (left + 1 < size && arr[left + 1] > arr[left]) ? left + 1 : left;
-
- //比较子节点和父节点
- if (arr[largest] > arr[index])
- Swap(arr, largest, index);
- else
- break;
-
- //循环结构
- index = largest;
- left = index * 2 + 1;
- }
- }
-
- void HeapSort(int* arr, int size)
- {
- int i = 0;
- if (arr == NULL || size < 2)
- return;
-
- //进二叉树:
- for (i = 1; i < size; i++)
- {
- HeapInsert(arr, i);
- }
-
- //排序:
- while (size > 0)
- {
- Swap(arr, 0, --size);
- HeapIfy(arr, 0, size);
- }
- }
-
- int main()
- {
- int arr[] = { 2, 3, 1, 3, 4, 5, 2, 8, 4, 7, 0, 8, 9, 3, 1 };
- int size = sizeof(arr) / sizeof(arr[0]);
- HeapSort(arr, size);
-
- for (int i = 0; i < size; i++)
- {
- printf("%d ", arr[i]);
- }
- system("pause");
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。