//堆排序 时间复杂度 O(nlogn) 空间复杂度 1 不稳定
//大顶堆(默认递增) 小顶堆 (默认递减)
//完全二叉树 满二叉树 二叉树
//二叉树 树形结构 且要求所有节点的分支不能超过2
//节点的度 一个节点向外伸出分支的个数
//叶子节点(中端节点);度为0的节点
//非叶子节点(分支节点);度不为0的节点
//父节点(双亲节点);
//子节点;
//满二叉树
//每一层的节点都摆满
//完全二叉树 相较于满二叉树 完全二叉树的最下面一层可以不用填满 但是最下面的一层必须节点是紧着左边填充
//大顶堆 首先其本身是一个完全二叉树,其要求每一个节点的值都大于其对于孩子节点的值(父大于子)
//第一步 将此时待排序序列构成的完全二叉树 调整为大顶堆 第一次调整为大顶堆
//由内到外调整成大顶堆
//第二步 此时调整好的大顶堆 其最大值就在其根节点的位置 则将其根节点的值与其最后一个节点的值进行交换,然后断开尾节点
//第三步 第二步头尾交换会导致不是大顶堆 此时需要将其调整为大顶堆
//第四步 反复执行23步 直到大顶堆剩下一个节点为止
//最后的最后 1 父节点怎么找其左右俩个子节点(根节点的下标为0) 父 i 子 2*i+1 2*i+2
//2 子节点怎么找其父节点 子 i 父 (i-1)/2
void Head_Adjust(int arr\[\], int start, int end)
{
//先将根节点的值 取出 放到tmp中
int tmp = arrstart;
//再申请一个变量maxchild 用来指向当前空白格子的较大者(默认指向其左孩子)
int maxchild = 0;
int leftchild = 2 * start + 1;
//进入for循环 循环条件是"当前"的空白格子是否有孩子(本质上是用maxchild是否合法来判断)
while(maxchild <= end)
{
//因为此时maxchild 默认保存的是空白格子的左孩子 这里进一步判断其右兄弟是否存在 且值更大
if (leftchild + 1 <= end && arrleftchild+1>arrleftchild)
{
maxchild = leftchild + 1;
}
if (arrmaxchild < =tmp)
{
arrstart = tmp;
return;
}
//可能性2 这个maxchild指向的较大的孩子的值>tmp的值 则将较大的孩子的值 想挪动到空白格子位置
//此时肯定出现新的空白格子 则让strat和maxchild更新一下 重新进入循环
else
{
arrstart = arrmaxchild;
start = maxchild;
leftchild = start * 2 + 1;
}
}
//如果while循环进不来 就说明此时的空白格子的左孩子下标非法 将tmp挪动回去 结束
arrstart = tmp;
return;
/*int temp = arrstart;
for (int i = 2 * start + 1; i <= end; i++)
{
if (i + 1 < end && arri < arri + 1)
{
i++;
}
if (arri < temp)
{
break;
}
arrstart = arri;
start = i;
}
arrstart = temp;*/
}
void Heap_Sort(int arr\[\], int len)
{
//1 将此时待排序序列构成的完全二叉树 由内到外调整为大顶堆 第一次调整为大顶堆
for (int i = (len - 1 - 1) / 2; i >= 0; i--)
{
Head_Adjust(arr, i, len - 1);
}
//4 反复执行23 直到大顶堆剩下一个节点为止(i代表要头尾交换的尾节点下标)
for (int i = len-1; i > 0; i--)
{
//2 头尾交换 然后断开尾部连接
int temp = arr0;//头
arr0 = arri;
arri = tmp;
//3 将头尾交换完成之后 大顶堆性质被破坏 需要再次调整成大顶堆
Head_Adjust(arr, 0, i-1);
}
//
}
//基数排序 从最低位(个位)开始对待排序序列整体处理一遍 然后进一步按"十位"对待排序序列整体处理 .....
//待排序序列整体处理 将待排序序列中的值,,按照此时要处理的"位" 将这个值插入到对应的队列中 直到所有的值
//全部插完 最后只需要从0->9号队列中将值全部取出
//时间复杂度 O(d(n+r)) 空间复杂度 O(n+r) 稳定
int Get_MaxNum_Figure(int arr\[\], int len)
{
int max = arr0;
for (int i = 1; i < len; i++)
{
if (arri > max)
max = arri;
}
if (max == 0)
return 1;
int num = 0;
while (max != 0)
{
max /= 10;
num++;
}
return num;
}
//3.获取当前值arri,在digit这一个位上,值是多少(插入到哪一个队列中)
//12345, 3 => 2
//12345, 1 => 4
//12345,5 => 0
int Get_Num_Digit(int num, int digit)
{
for (int i = 0; i < digit; i++)
num /= 10;
return num % 10;
}
#include <queue>
//单独处理一遍, //digit=0代表按个数处理 digit=1代表按十位处理
void Radix(int arr\[\], int len, int digit)
{
std::queue<int> Buckets10;
//2.进入for循环,依次访问待排序序列全部元素
for (int i = 0; i < len; i++)
{
//3.获取当前值arri,在digit这一个位上,值是多少(插入到哪一个队列中)
int index = Get_Num_Digit(arri, digit);
Bucketsindex.push(arri);
}
//5.此时待排序序列所以的数据,都已经插入到对应的队列中了,最后只需要将0->9号队列值依次取出即可
int k = 0;
for (int i = 0; i <= 9; i++)//i代表队列号
{
//6.将此时i号队列中的值,全部取出放到arri中
while (!Bucketsi.empty())
{
arrk++ = Bucketsi.front();
Bucketsi.pop();
}
}
}
void Radix_Sort(int arr\[\], int len)
{
int fig = Get_MaxNum_Figure(arr, len);
//2.进入for循环,只要i还合法
for (int i = 0; i < fig; i++)//i=0代表按个数处理 i=1代表按十位处理
{
Radix(arr, len, i);
}
}