经典排序算法解析(四)

简介: 经典排序算法解析

八、堆排序


   堆排序是比快速排序更加复杂的一种排序算法。堆排序使用到了堆这样一种数据结构。首先我们需要搞清楚什么是堆结构。堆是一种类似完全二叉树,同时又满足如下条件的数据结构:所有子节点的值总是小于(大于)父节点。所有子节点的值都小于父节点的堆叫大顶堆,所有子节点都大于父节点的堆叫小顶堆。


   二叉树你应该比较熟悉,下图就是一个小顶堆的示例:


image.png


此二叉树中任何一个子节点的值都是大于父节点。如何将数列构造成这样一个堆结构呢,其实十分简单,将数列按照从上到下,从左到右的原则来构造完全二叉树即可。例如如下数列[1, 54, 2, 64, 12, 65, 76, 46, 34, 98, 34]如果将其构造成堆如下图所示:

image.png



正常情况下,这个由数组映射成的二叉树并不符合我们堆的要求,否则也就不需要我们用算法来排序了。要让这个二叉树符合要求,我们需要进行整理,即从末节点开始进行调整,例如先从12,98,34中找到最小的,放在现在12所在的位置,然后从64,46,34中找到最小的元素进行上浮,接着再一层层上浮上去,直到堆顶元素为所有元素中的最小元素。整理完成后,我们只需要将堆顶元素和最后一个元素进行交换,之后除掉最后一个元素再进行堆整理,整理完成后再将顶元素(此时为第2小)与倒数第二个元素交换,依次进行下去,即可完成数列的排序。


   用文字描述堆排序步骤如下:


1.先将数列整理成符合要求的堆。


2.将首末元素交换。


3.除掉最后一个元素在进行堆的整理。


4.重复进行2和3,直到数列排序完成。


JavaScript实现的堆排序算法:


var array = [1, 54, 2, 64, 12, 65, 76, 46, 34, 98, 34];

//堆排序

//堆调整 大顶

function store(array,index,end){

let top = array[index];

let left;

let right;

if (index*2+1<=end) {

 left = index*2+1;

}else{

 //没有左子树 说明已经是叶子节点

 //无需调整直接return

 return;

}

if (index*2+2<=end) {

 right = index*2+2;

}else{

 //没有右子树 调整左子树即可

 if (array[left]>top) {

  array[index] = array[left];

  array[left] = top;

  top = array[index];

 }

 return;

}

//找出堆单元中的最大值

if (array[left]>top) {

 array[index] = array[left];

 array[left] = top;

 top = array[index];  

}

if (array[right]>top) {

 array[index] = array[right];

 array[right] = top;

 top = array[index];

}

}

function sort(array,end){

//先将堆进行调整 倒叙调整

let i = end;

while(i>=0){

 store(array,i,end)

 i--;

}

//根节点一定是最大的 放最后 再进行堆整理

let temp = array[end];

array[end] = array[0];

array[0] = temp;

end--;

if (end>0) {

 sort(array,end);

}else{

 return;

}


}

sort(array, array.length-1);

console.log(array); //[ 1, 2, 12, 34,34, 46, 54, 64, 65, 76, 98 ]

C语言实现的堆排序算法:


#include <stdio.h>

void store(int array[],int index,int end){

int top = array[index];

int left;

int right;

if (index*2+1<=end) {

 left = index*2+1;

}else{

 //没有左子树 说明已经是叶子节点

 //无需调整直接return

 return;

}

if (index*2+2<=end) {

 right = index*2+2;

}else{

 //没有右子树 调整左子树即可

 if (array[left]>top) {

  array[index] = array[left];

  array[left] = top;

  top = array[index];

 }

 return;

}

//找出堆单元中的最大值

if (array[left]>top) {

 array[index] = array[left];

 array[left] = top;

 top = array[index];  

}

if (array[right]>top) {

 array[index] = array[right];

 array[right] = top;

 top = array[index];

}

}

void mySort(int array[],int end){

//先将堆进行调整 倒叙调整

int i = end;

while(i>=0){

 store(array,i,end);

 i--;

}

//根节点一定是最大的 放最后 再进行堆整理

int temp = array[end];

array[end] = array[0];

array[0] = temp;

end--;

if (end>0) {

 mySort(array,end);

}else{

 return;

}


}

int main(){

int a[] = {1, 2, 12, 34, 46, 54, 64, 65, 76, 98,34};

mySort(a,10);

for(int i = 0;i<11;i++){

 printf("%d\n",a[i]);

}

return 0;

}

需要注意,大顶堆排序完成后为升序,小顶堆排序完成后为降序。


九、归并排序


   归并排序的核心并不是交换元素的顺序,而是将数列分成多个有序小数列,将相邻的小数列进行归并。文字描述归并排序步骤如下:


1.把长度为n的数列分成长度为1的n个数列。


2.相邻数列进行排序归并。


3.重复操作2,直到所有数列归并成1个整体。


JavaScript实现的归并排序算法:


var array = [1, 54, 2, 64, 12, 65, 76, 46, 34, 98, 34];

//归并排序

function mergeArray(arrL,arrR){

var tempArray = new Array();

let i = 0;

let j = 0;

while(i<arrL.length && j<arrR.length){

 if (arrL[i]<arrR[j]) {

  tempArray.push(arrL[i]);

  i++;

 }else{

  tempArray.push(arrR[j]);

  j++;

 }

}

while(i<arrL.length){

 tempArray.push(arrL[i]);

 i++;

}

while(j<arrR.length){

 tempArray.push(arrR[j]);

 j++

}

return tempArray;

}

function sort(array){

if (array.length>1) {

 let arrL = array.slice(0,Math.floor(array.length/2));

 let arrR = array.slice(Math.floor(array.length/2),array.length);

 if (arrL.length>1) {

  arrL = sort(arrL);

 }

 if (arrR.length>1) {

  arrR = sort(arrR);

 }

 return mergeArray(arrL,arrR);

}

return array;

}

console.log(sort(array)); //[ 1, 2, 12, 34,34, 46, 54, 64, 65, 76, 98 ]

C语言实现的归并排序算法:


#include <stdio.h>

void merge(int array[],int temp[],int start,int end,int middle){

int i=start,j=middle+1,k=start;

while(i<middle+1 && j<end+1){

 if(array[i]<array[j]){

  temp[k++] = array[i++];

 }else {

  temp[k++] = array[j++];

 }

}

while(i<middle+1){

 temp[k++] = array[i++];

}

while(j<end+1){

 temp[k++] = array[j++];

}

for(i=start;i<=end;i++){

 array[i] = temp[i];

 // printf("%d,",temp[i]);

}

}

void sort(int array[],int temp[],int start,int end){

int middle;

if(start<end){

 middle = (start+end)/2;

 sort(array, temp, start, middle);

 sort(array, temp, middle+1, end);

 merge(array, temp, start, end, middle);

}

}

int main(){

int a[] = {1, 2, 12, 34, 46, 54, 64, 65, 76, 98,34};

int b[11] = {0};

sort(a,b,0,10);

for(int i = 0;i<11;i++){

 printf("%d\n",a[i]);

}

return 0;

}

目录
相关文章
|
3月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
4月前
|
机器学习/深度学习 人工智能 搜索推荐
从零构建短视频推荐系统:双塔算法架构解析与代码实现
短视频推荐看似“读心”,实则依赖双塔推荐系统:用户塔与物品塔分别将行为与内容编码为向量,通过相似度匹配实现精准推送。本文解析其架构原理、技术实现与工程挑战,揭秘抖音等平台如何用AI抓住你的注意力。
983 7
从零构建短视频推荐系统:双塔算法架构解析与代码实现
|
4月前
|
机器学习/深度学习 存储 算法
动态规划算法深度解析:0-1背包问题
0-1背包问题是经典的组合优化问题,目标是在给定物品重量和价值及背包容量限制下,选取物品使得总价值最大化且每个物品仅能被选一次。该问题通常采用动态规划方法解决,通过构建二维状态表dp[i][j]记录前i个物品在容量j时的最大价值,利用状态转移方程避免重复计算子问题,从而高效求解最优解。
564 1
|
4月前
|
算法 搜索推荐 Java
贪心算法:部分背包问题深度解析
该Java代码基于贪心算法求解分数背包问题,通过按单位价值降序排序,优先装入高价值物品,并支持部分装入。核心包括冒泡排序优化、分阶段装入策略及精度控制,体现贪心选择性质,适用于可分割资源的最优化场景。
345 1
贪心算法:部分背包问题深度解析
|
4月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
4月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
机器学习/深度学习 算法 自动驾驶
735 0
|
4月前
|
机器学习/深度学习 人工智能 资源调度
大语言模型的核心算法——简要解析
大语言模型的核心算法基于Transformer架构,以自注意力机制为核心,通过Q、K、V矩阵动态捕捉序列内部关系。多头注意力增强模型表达能力,位置编码(如RoPE)解决顺序信息问题。Flash Attention优化计算效率,GQA平衡性能与资源消耗。训练上,DPO替代RLHF提升效率,MoE架构实现参数扩展,Constitutional AI实现自监督对齐。整体技术推动模型在长序列、低资源下的性能突破。
514 8
|
4月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
6月前
|
机器学习/深度学习 人工智能 编解码
AI视觉新突破:多角度理解3D世界的算法原理全解析
多视角条件扩散算法通过多张图片输入生成高质量3D模型,克服了单图建模背面细节缺失的问题。该技术模拟人类多角度观察方式,结合跨视图注意力机制与一致性损失优化,大幅提升几何精度与纹理保真度,成为AI 3D生成的重要突破。
558 0

热门文章

最新文章

推荐镜像

更多
  • DNS