堆排序
通过阅读《算法导论》第六章,学习了堆排序。
本文主要列出堆排序算法执行步骤和C++、Python代码。
算法名次 | 堆排序 |
---|---|
类别 | 排序算法 |
复杂度 | nlgn |
实现形式 | 链表,数组(原地址排序) |
参考书 | 算法导论 |
C++代码
#include <iostream>
/////////////////////
//思路:
//1、建立函数max_heapify:用于对指定节点执行堆排序
//2、建立函数build_max_heap:调用函数max_heapify,便利所有非叶子节点,建立一个最大堆
//3、建立函数heap_sort:调用函数build_max_heap建立一个最大堆后,将跟节点与与最后一个节点交换,再调用函数max_heapify(除最后一个节点外)对根节点执行对排序,然后重复上述操作,直到所有节点执行完毕节点
/////////////////////
/////////////////////
//函数名:max_heapify
//函数功能:对指定节点执行堆排序
//输入变量:
// heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
// index:整型,待排序节点的下标
// heap_length:整型,待排序堆的节点个数
//输出变量:无
/////////////////////
void max_heapify(int heap_array[], int index, int heap_length)
{
int left_index = index * 2; //存放左子节点下标
int right_index = index * 2 + 1; //存放右子节点下标
int larger_index = index; //存放较大子节点下标
//如果左子节点大于根节点,则larger_index标签转换
if((left_index <= heap_length) && (heap_array[left_index] > heap_array[index]))
larger_index = left_index;
//如果右子节点大于较大节点,则larger_index标签转换
if((right_index <= heap_length) && (heap_array[right_index] > heap_array[larger_index]))
larger_index = right_index;
//如果根节点不是最大的,则进行交换,并继续对对应的子节点执行排序操作(递归调用)
if(larger_index != index)
{
int tmp_value = heap_array[index];
heap_array[index] = heap_array[larger_index];
heap_array[larger_index] = tmp_value;
max_heapify(heap_array, larger_index, heap_length);
}
}
/////////////////////
//函数名:build_max_heap
//函数功能:调用函数max_heapify,便利所有非叶子节点,建立一个最大堆
//输入变量:
// heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
// heap_length:整型,待排序堆的节点个数,最后一个非叶子节点为heap_length/2
//输出变量:无
/////////////////////
void build_max_heap(int heap_array[], int heap_length)
{
int last_leaf_index = heap_length / 2;
//从最后一个非叶子节点到根节点,依次进行堆排序
for(int index = last_leaf_index; index >= 1; --index)
max_heapify(heap_array, index, heap_length);
}
/////////////////////
//函数名:heap_sort
//函数功能:调用函数build_max_heap建立一个最大堆后,将跟节点与与最后一个节点交换,再调用函数max_heapify(除最后一个节点外)对根节点执行对排序,然后重复上述操作,直到所有节点执行完毕节点
//输入变量:
// heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
// heap_length:整型,待排序堆的节点个数,最后一个非叶子节点为heap_length/2
//输出变量:无
/////////////////////
void heap_sort(int heap_array[], int heap_length)
{
//获得第一个最大堆
build_max_heap(heap_array, heap_length);
for(int index = heap_length; index >= 2; --index)
{
//将最大节点(根节点)调整到最后一个节点
int tmp_value = heap_array[index];
heap_array[index] = heap_array[1];
heap_array[1] = tmp_value;
//对根节点(基于剩余节点的堆)执行堆排序
max_heapify(heap_array, 1, index - 1);
}
}
int main()
{
int array[] = {-9999, 1, 234, 45, 67, 21, 975, 5275, 867, -12, -200};
int num = 10;
printf("待排序数组顺序为:");
for(int i = 1; i <= num; ++i)
printf("%d ", array[i]);
printf("\n");
heap_sort(array, num);
printf("已排序序数组顺序为:");
for(int i = 1; i <= num; ++i)
printf("%d ", array[i]);
printf("\nFinished.\n");
return 0;
}
执行结果:
待排序数组顺序为:1 234 45 67 21 975 5275 867 -12 -200
已排序序数组顺序为:-200 -12 1 21 45 67 234 867 975 5275
Finished.
Press any key to continue…
Python代码
####################
#思路:
#1、建立函数max_heapify:用于对指定节点执行堆排序
#2、建立函数build_max_heap:调用函数max_heapify,便利所有非叶子节点,建立一个最大堆
#3、建立函数heap_sort:调用函数build_max_heap建立一个最大堆后,将跟节点与与最后一个节点交换,再调用函数max_heapify(除最后一个节点外)对根节点执行对排序,然后重复上述操作,直到所有节点执行完毕节点
####################
####################
#函数名:max_heapify
#函数功能:对指定节点执行堆排序
#输入变量:
# heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
# index:整型,待排序节点的下标
# heap_length:整型,待排序堆的节点个数
#输出变量:无
####################
def max_heapify(heap_array, index, heap_length):
left_index = index * 2 #存放左子节点下标
right_index = index * 2 + 1 #存放右子节点下标
larger_index = index #存放较大子节点下标
#如果左子节点大于根节点,则larger_index标签转换
if left_index <= heap_length and heap_array[left_index] > heap_array[index]:
larger_index = left_index
#如果右子节点大于较大节点,则larger_index标签转换
if right_index <= heap_length and heap_array[right_index] > heap_array[larger_index]:
larger_index = right_index
#如果根节点不是最大的,则进行交换,并继续对对应的子节点执行排序操作(递归调用)
if larger_index != index:
tmp_value = heap_array[index]
heap_array[index] = heap_array[larger_index]
heap_array[larger_index] = tmp_value
max_heapify(heap_array, larger_index, heap_length)
####################
#函数名:build_max_heap
#函数功能:调用函数max_heapify,便利所有非叶子节点,建立一个最大堆
#输入变量:
# heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
# heap_length:整型,待排序堆的节点个数,最后一个非叶子节点为heap_length/2
#输出变量:无
####################
def build_max_heap(heap_array, heap_length):
last_leaf_index = int(heap_length / 2)
#从最后一个非叶子节点到根节点,依次进行堆排序
for index in range(last_leaf_index, 0, -1):
max_heapify(heap_array, index, heap_length)
####################
#函数名:heap_sort
#函数功能:调用函数build_max_heap建立一个最大堆后,将跟节点与与最后一个节点交换,再调用函数max_heapify(除最后一个节点外)对根节点执行对排序,然后重复上述操作,直到所有节点执行完毕节点
#输入变量:
# heap_array:堆数组(下标从1开始),节点i的左右子节点分别为2*i和2*i+1
# heap_length:整型,待排序堆的节点个数,最后一个非叶子节点为heap_length/2
#输出变量:无
####################
def heap_sort(heap_array, heap_length):
#获得第一个最大堆
build_max_heap(heap_array, heap_length)
for index in range(heap_length, 1, -1):
#将最大节点(根节点)调整到最后一个节点
tmp_value = heap_array[index]
heap_array[index] = heap_array[1]
heap_array[1] = tmp_value
#对根节点(基于剩余节点的堆)执行堆排序
max_heapify(heap_array, 1, index - 1)
if __name__ == '__main__':
array = [-9999, 1, 234, 45, 67, 21, 975, 5275, 867, -12, -200]
print("待排序数组为:", array[1 : ])
heap_sort(array, 10)
print("已排序数组为:", array[1 : ])
执行结果:
python3 heap_sort.py
待排序数组为: [1, 234, 45, 67, 21, 975, 5275, 867, -12, -200]
已排序数组为: [-200, -12, 1, 21, 45, 67, 234, 867, 975, 5275]