经过几次C语言笔试,发现经常会被问到求1万个数中前100大的数,现在想了两种方法来解决:
方法一:一维数值
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//求数组的最大值,返回b【0】
int max(int b[],int n)
{
int i,t,k=0,m=0;
int c=n;
//将数组两两进行比较,把较大值至于最前面
while(n!=1)
{
for(i=0;i<n;i++)
{
if(b[i]>b[i+1])
{
t=0;
t=b[i];
b[i]=b[i/2];
b[i/2]=t;
}
else{
t=0;
t=b[i+1];
b[i+1]=b[i/2];
b[i/2]=t;
}
i++;
}
n=n/2;
}
m=b[0];
return m;
}
int main(int argc, char *argv[])
{
int *test,i,k,d=0,x=0,y=0;
int l=100000,h=100; //l表示数的总个数,h表示要求的前h大数
int m[h];
d=l;
if(d&(d-1))
{
while(d>1){
d>>=1;
x++;}
x++;
}
else
{
while(d>1){
d>>=1;
x++;} //x表示要进行的比较次数,y表示要申请的空间大小
}
y=pow(2,x);
srand(time(0));
test=(int *)malloc(sizeof(int)*y);
for(long a=0;a<l;a++)
{
test[a]=rand()%100000+1; //动态生成随机数
printf("%d ",test[a]);
}
printf("\n");
for(i=l;i<y;i++)
{
test[i]=0;
}
m[0]=max(test,y);
for(i=1;i<h;i++)
{
for(k=0;k<l;k++)
{
if(test[k]==m[i-1])
test[k]=0;
}
m[i]=max(test,y);
}
printf("这%d个数中前%d大的数分别为:\n",l,h);
for(i=0;i<h;i++)
{
printf("%d ",m[i]);
}
printf("\n");
printf("单次比较次数为:%d\n",x);
printf("总计比较次数为:%d\n",h*x);
printf("\n");
free(test);
test=NULL;
return 0;
}
方法二:哈夫曼树
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
struct BTreeNode
{
ElemType data;
struct BTreeNode* left;
struct BTreeNode* right;
};
//根据数组 a 中 n 个权值建立一棵哈夫曼树,返回树根指针
struct BTreeNode* CreateHuffman(ElemType a[], int n)
{
int i, j;
struct BTreeNode **b, *q;
b = (BTreeNode **)malloc(sizeof(struct BTreeNode)*n);
for (i = 0; i < n; i++) //初始化b指针数组,使每个指针元素指向a数组中对应的元素结点
{
b[i] = (BTreeNode *)malloc(sizeof(struct BTreeNode));
b[i]->data = a[i];
b[i]->left = b[i]->right = NULL;
}
for (i = 1; i < n; i++)//进行 n-1 次循环建立哈夫曼树
{
//k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
int k1 = -1, k2;
for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵
{
if (b[j] != NULL && k1 == -1)
{
k1 = j;
continue;
}
if (b[j] != NULL)
{
k2 = j;
break;
}
}
for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小
{
if (b[j] != NULL)
{
if (b[j]->data < b[k1]->data)
{
k2 = k1;
k1 = j;
}
else if (b[j]->data < b[k2]->data)
k2 = j;
}
}
//由最小权值树和次最小权值树建立一棵新树,q指向树根结点
q = (BTreeNode *)malloc(sizeof(struct BTreeNode));
q->data = b[k2]->data;
q->left = b[k1];
q->right = b[k2];
b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置
b[k2] = NULL;//k2位置为空
}
free(b); //删除动态建立的数组b
return q; //返回整个哈夫曼树的树根指针
}
int main(int argc, char *argv[])
{
int *test;
int l=100,h=10,i,k;
int m[h];
struct BTreeNode* q;
srand(time(0));
test=(int *)malloc(sizeof(int)*l);
for(long a=0;a<l;a++)
{
test[a]=rand()%100+1;
printf("%d ",test[a]);
}
printf("\n");
q=CreateHuffman(test,l);
m[0]=q->data;
for(i=1;i<h;i++)
{
for(k=0;k<l;k++)
{
if(test[k]==m[i-1])
test[k]=0;
}
q=CreateHuffman(test,l);
m[i]=q->data;
}
printf("这%d个数中前%d大的数分别为:\n",l,h);
for(i=0;i<h;i++)
{
printf("%d ",m[i]);
}
printf("\n");
printf("比较次数为:%d",l-1);
printf("\n");
return 0;
}
运行结果如下: