数据结构(堆排序,基数排序)

//堆排序 时间复杂度 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 = arr[start];

//再申请一个变量maxchild 用来指向当前空白格子的较大者(默认指向其左孩子)

int maxchild = 0;

int leftchild = 2 * start + 1;

//进入for循环 循环条件是"当前"的空白格子是否有孩子(本质上是用maxchild是否合法来判断)

while(maxchild <= end)

{

//因为此时maxchild 默认保存的是空白格子的左孩子 这里进一步判断其右兄弟是否存在 且值更大

if (leftchild + 1 <= end && arr[leftchild+1]>arr[leftchild])

{

maxchild = leftchild + 1;

}

if (arr[maxchild] < =tmp)

{

arr[start] = tmp;

return;

}

//可能性2 这个maxchild指向的较大的孩子的值>tmp的值 则将较大的孩子的值 想挪动到空白格子位置

//此时肯定出现新的空白格子 则让strat和maxchild更新一下 重新进入循环

else

{

arr[start] = arr[maxchild];

start = maxchild;

leftchild = start * 2 + 1;

}

}

//如果while循环进不来 就说明此时的空白格子的左孩子下标非法 将tmp挪动回去 结束

arr[start] = tmp;

return;

/*int temp = arr[start];

for (int i = 2 * start + 1; i <= end; i++)

{

if (i + 1 < end && arr[i] < arr[i + 1])

{

i++;

}

if (arr[i] < temp)

{

break;

}

arr[start] = arr[i];

start = i;

}

arr[start] = 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 = arr[0];//头

arr[0] = arr[i];

arr[i] = 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 = arr[0];

for (int i = 1; i < len; i++)

{

if (arr[i] > max)

max = arr[i];

}

if (max == 0)

return 1;

int num = 0;

while (max != 0)

{

max /= 10;

num++;

}

return num;

}

//3.获取当前值arr[i],在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)

{

//1.申请10个队列

std::queue<int> Buckets[10];

//2.进入for循环,依次访问待排序序列全部元素

for (int i = 0; i < len; i++)

{

//3.获取当前值arr[i],在digit这一个位上,值是多少(插入到哪一个队列中)

int index = Get_Num_Digit(arr[i], digit);

//4.将该值插入到对应的队列中

Buckets[index].push(arr[i]);

}

//5.此时待排序序列所以的数据,都已经插入到对应的队列中了,最后只需要将0->9号队列值依次取出即可

int k = 0;

for (int i = 0; i <= 9; i++)//i代表队列号

{

//6.将此时i号队列中的值,全部取出放到arr[i]中

while (!Buckets[i].empty())

{

arr[k++] = Buckets[i].front();

Buckets[i].pop();

}

}

}

void Radix_Sort(int arr[], int len)

{

//1.先获取待排序序列中最大值的位数

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);

}

}

相关推荐
什仙1 小时前
Ansys Maxwell 默认求解器选择
人工智能·笔记·算法·基础·ansys·maxwell
weixin_307779131 小时前
基于Vosk与CTranslate2的实时语音识别翻译系统 —— 完整C++实现详解
人工智能·算法·自动化·语音识别·原型模式
akarinnnn1 小时前
深入理解内存函数:原理、应用与优化
c语言·网络·数据结构·算法
一行代码一行诗++1 小时前
for循环中的break和continue
数据结构·算法
Tisfy1 小时前
LeetCode 3043.最长公共前缀的长度:哈希表(不转string)
算法·leetcode·散列表·题解·哈希表
代码中介商1 小时前
排序算法完全指南(三):插入排序深度详解
算法·排序算法
承渊政道1 小时前
【贪心算法】(经典实战应用解析(六):整数替换、俄罗斯套娃信封问题、可被三整除的最⼤和、距离相等的条形码、重构字符串)
c++·算法·leetcode·贪心算法·排序算法·动态规划·哈希算法
WL_Aurora1 小时前
Python 算法基础篇之排序算法(二):希尔、快速、归并
python·算法·排序算法
闻缺陷则喜何志丹1 小时前
【图论 树 启发式合并】P7165 [COCI2020-2021#1] Papričice|普及+
c++·算法·启发式算法·图论··洛谷