今天準備把之前遇到過的經典算法都自己根據理解寫一遍。這是一個很好的提高編程技巧的過程。
這次寫的算法是堆排序,雖然我知道我這個算法在對於網上衆多堆排序算法簡直就像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;
}