今天准备把之前遇到过的经典算法都自己根据理解写一遍。这是一个很好的提高编程技巧的过程。
这次写的算法是堆排序,虽然我知道我这个算法在对于网上众多堆排序算法简直就像XXXX的裹脚布一样XXXX....但是些算法这种东西我一直觉得都是可以精简精简再精简,慢慢改改就会好,但是我还是不想发优化后的堆排序算法,因为那样就会忽略掉自己编程中的一些思路问题与一些犯的错误。
这次贴的代码乱七八糟的,希望能给有些同学带来一些思路的同时给大家一些提醒....
现在来谈谈我对堆排序的简单粗暴的理解吧:
泛泛的谈就是一个递归的过程。
个人觉得堆排序还是一个很不错的算法,体现了很多编程的思想,大家如果能都自己不看别人的事例代码自己敲一遍那是极好...我去看别人写的事例代码了,看看比我写得好在哪...下面,上代码...(这次用的是VC++6.0的编译器,个人感觉比VS2010真TMD难用很多,而且还有一些BUG,不过没办法,听说很多地方机试都是用这个编译器)
//堆排序
/*
调用方式:HeadSort(a,MAXSIZE,cmp_2);最后一个参数如果是cmp_1为非递减排列,cmp_2为非递增排列
*/
#include "stdafx.h"
#include <time.h>
#include <stdlib.h>
//调整堆(大堆 1为< 2为>)
void HeadAdjust(int a[],int i,int size,const int (*cmp)(const int,const int))
{//i为逻辑编号,1开始算起,cmp为比较函数
int *lchild = NULL;//左孩子
int *rchild = NULL;//右孩子
int temp;
if(2*i > size)//i节点为叶子节点
return ;
// do
// {
if(2*i < size)//i为有左,右孩子的非叶子节点
{
lchild = &a[2*i-1];
rchild = &a[2*i];
int *best = cmp(*lchild,*rchild) ? rchild : lchild;//改2
if(cmp(a[i-1],*best))//改1
{
temp = a[i-1];
a[i-1] = *best;
*best = temp;
}
i = best-a + 1;
}
if(2*i == size)//i为只有左孩子的飞叶子节点
{
lchild = &a[2*i-1];
if(cmp(a[i-1],*lchild))//改1
{
temp = a[i-1];
a[i-1] = *lchild;
*lchild = temp;
}
return ;
// break;
}
HeadAdjust(a,i,size,cmp);
// }while(cmp(a[i],a[2*i-1]) || cmp(a[i],a[2*i]));//改1
}
void BuildHead(int a[],int size,const int (*cmp)(const int,const int))
{
for(int i = size;i > 0;--i)
{
HeadAdjust(a,i,size,cmp);
}
}
void HeadSort(int a[],int size,const int (*cmp)(const int,const int))
{
int temp;
BuildHead(a,size,cmp);
for(int i = size;i > 0;--i)
{
temp = a[i-1];
a[i-1] = a[0];
a[0] = temp;
HeadAdjust(a,1,i-1,cmp);
}
}
//非递减
const int cmp_1(const int a,const int b)
{
return a<=b;
}
//非得增
const int cmp_2(const int a,const int b)
{
return a>=b;
}
#define MAXSIZE 100
int main(int argc, char* argv[])
{
int a[MAXSIZE]={0};
srand(time(0));
for(int i = 0;i < MAXSIZE;++i)
{
a[i] = rand()%MAXSIZE;
}
// int a[] = {0,0,3,4,1,2,7,9,9,9};
HeadSort(a,MAXSIZE,cmp_2);
printf("Hello World!\n");
return 0;
}