如果你已经学会C,C++(或看过《C++Primer》)的基本语法,想要再精进一层的话,那就是该接触数据结构与算法的时候了,这个系列博文的主题亦如此,所提供的代码都是在学习这些的过程中,自己写的代码,且亲测有效。
无数前辈说过,程序 = 数据结构 + 算法,数据结构就是内存对数据的存储方式,算法就是对数据的加工处理。那么对于超大量的数据,为了管理他们,为了以后好取出想要的值,对他们的加工处理基本上都是按照各种排序方式,排来排去。
《Effictive C++》赞美之音传于四海,这本书的中文翻译者侯捷,他老人家更是桃李满天下。他第一次听人说了电脑就是对存进来的数据排一下序,很难相信,他认为因为电脑是一种顶级高科技的存在,是用来发射火箭的,怎么就只排排数据。所以很容易忽略排序的重要性,因为我们平时都是处理的小量数据,想取哪一个数据手动,输出一下就行了。
举个业务上的例子,现在各个银行都在建设5G银行,系统会保存客户的人脸图片,当客户下次去银行的时候,门口会有声音欢迎王先生光临~。因为门口会有摄像头做人脸拍照,然后与数据库的照片比对排序。这种比对是一个个比吗,如果客户在上亿的量,一个个比太慢了,系统的实现是按照图片上的特性值,把之前在数据库中存的上亿照片按照一定的方式排序,这样就不需要一个个比对,可以用二分查找这类方法快速找到。
排序算法,分两部分,业务 + 代码,业务即是算法怎么实现这个功能的,文字上描述一下,代码是具体是实现。无论上个小系列数据结构还是接下来的算法,我都将采用这种方式讲解。理解业务更易看懂代码,然有些业务说起来很抽象,照猫画虎的不好文字描述,直接看代码范围理解快一点,所以两者可以结合着来理解。
刚开始学前几个排序时,这些排序是最简单的也是最难的,最简单是因为学了好久之后再回来看,最难是因为刚刚接触的前几个排序,一看晕了,再看排序算法这么多,放弃了。其实不然,只要学会几个,后面就会很轻松,还有助于你以更高的视野看前面学过的算法。
堆排序是对完全二叉树的排序,若最终排序是,树从下到上,树的每一层从右至左,依次增大的话。堆排序提纲挈领的来说分为三部分:1)将完全二叉树初始化为大顶堆(每个父节点均大于它的两个孩子结点,具体看代码实现)。 2)将初始化的最顶层父节点与树的未排序的最后结点交换。3)重复1)后重复2)。每次重复1)后,再重复2)时,跟最顶层结点交换的是,从下都上,从右至左的每个结点。
郭襄:我走过山时,山不说话,我路过海时,海不说话。
很多时候,这个世界是自己的跟他人无关,生活需要自己去探索。
上代码,亲测有效!
#include <iostream>
#include <string>
using namespace std;
//打印
void Print(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("数组元素:%d ", arr[i]);
}
printf("\n");
}
//交换接口
void Swap(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
return;
}
//初始化大顶堆
//increase是二叉树第一个位置为1计起的增量
void Adjust(int myArray[], int size, int increase)
{
int lChild = increase * 2 - 1;
int rChild = increase * 2;
int i = increase - 1;
int max = i;
if (myArray[i] < myArray[lChild] && lChild < size)
{
max = lChild;
}
if (myArray[max] < myArray[rChild] && rChild < size)
{
max = rChild;
}
if (max != i)//将节点与最大的孩子互换位置
{
int temp;
temp = myArray[i];
myArray[i] = myArray[max];
myArray[max] = temp;
//交换完成后,max位置父节点可能小于子节点
//再调整一次,使其满足大顶堆
if (2 * (max + 1) + 1 <= size) //防止越界
{
Adjust(myArray, size, max + 1);
}
}
}
//将数组按照左小右大依次排序
void HeapSort(int arr[], int size)
{
//初始化堆,使其成为大顶堆
for (int increase = size / 2; increase >= 1; increase--)
{
Adjust(arr, size, increase);
}
for (int i = size - 1; i > 0; i--)
{
//将顶堆与最后一位未排序节点交换
Swap(&arr[i], &arr[0]);
size--;
//交换完后,再使其成为大顶堆
Adjust(arr, size, 1);
}
}
int main(void)
{
int arr[10] = { 2, 1, 4, 3, 6, 5, 8, 7, 0, 9 };
Print(arr, 10);
HeapSort(arr, 10);
Print(arr, 10);
system("pause");
return 0;
}