a设有N个数,要确定其中第k个最大者,(我实现的是第k个最小者),也就是选择问题,C语言实现:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define TOTAL_NUMBER 100000
#define KTH 50
//函数声明
void displayArray(int *data, int length, const char * preDisplay);
/*
* 产生指定数量的随机数
*/
int* generateIntergerArray(int totalNumber)
{
int* numberArray = (int *)malloc(sizeof(int)*totalNumber);
int i = 0;
for(i = 0; i<totalNumber; i++)
{
*(numberArray + i) = rand();
}
return numberArray;
}
/*
* 冒泡法对随机数组进行排序,从小到大
*/
int * bubleSort(int * data,int length)
{
int i = 0;
int j = 0;
// 变量i用来控制比较的范围,每次少比较右面的一个数,也就是最大的那个数
for(i = 0; i < length - 1; i++) //i:= 0,1,2...,length -2,一共length-1次比较
{
// 变量j用来对数组中的数逐个比较,j为索引
// 每次比较从第2个开始,到第length - i - 1个结束。当i=0时,data[length-1]就是最后一个数
for(j = 1; j <= length - i - 1; j++)
{
int temp = 0;
// 如果前一个数大于后一个数,那么这两个数互换。
if(*(data + j - 1) > *(data + j))
{
temp = *(data + j - 1);
*(data + j - 1) = *(data + j);
*(data + j) = temp;
}
}
// displayArray(data,length,"-------->");
}
return data;
}
/*
* 输出数组中的数
*/
void displayArray(int *data, int length,const char * preDisplay)
{
printf(preDisplay);
int i = 0;
for(i = 0;i < length; i++)
{
printf("%d,",*(data+i));
}
printf("\n\n");
}
/*
* 显示数组中的第k个数
*/
void displayKthElement(int *data, int k,const char * preDisplay)
{
printf(preDisplay);
printf("%d\n\n",*(data + k - 1));
}
/*
* 使用插入法,寻找第k个大的数
*/
int insertAlgorithm(int * data,int length, int kth)
{
assert(length >= kth);
// 建立长度为k的数组
int* kLengthArray = (int*)malloc(sizeof(int)*kth);
//将data中的前k个数读入kLengthArray中
int i = 0;
for(i = 0; i < kth; i++)
{
*(kLengthArray + i) = *(data + i);
}
// 使用冒泡法对kLengthArray进行排序
kLengthArray = bubleSort(kLengthArray, kth);
// displayArray(kLengthArray,kth,"the fist kLengthArray is: \n");
// 对剩下的数据进行插入
int count = kth; // 从第kth+1个数开始进行插入
int index = kth - 1; // 从右往左插入,即从第kth个数开始插入
for(count = kth; count <= length - 1; count++) // 使用第count个数进行比较,然后插入
{
// 得到插入的数在kLengthArray中的位置 index
for(index = kth - 1; index >= -1; index--)
{
if (*(data + count) > *(kLengthArray + index))
{
break;
}
}
// 如果index不能维持原值,那么存在一个数在kLengthArray的数的中间,需要进行插入操作
if (index != kth - 1)
{
int i = 0;
for(i = 0; i < kth - index - 2; i++)
{
*(kLengthArray + kth - i - 1) = *(kLengthArray + kth - i - 2);
}
*(kLengthArray + index + 1) = *(data + count);
}
}
// displayArray(kLengthArray,kth,"the final kLengthArray is: \n");
return *(kLengthArray + kth - 1);
}
int main()
{
int* numbers;
numbers = generateIntergerArray(TOTAL_NUMBER);
// displayArray(numbers, TOTAL_NUMBER, "random number generated is:\n");
// 使用冒泡法得到第k个大的数
int * numbersForBuble = (int*)malloc(sizeof(int)*TOTAL_NUMBER);
numbersForBuble = bubleSort(numbers,TOTAL_NUMBER);
displayKthElement(numbersForBuble,KTH,"the k-th element computed by buble algorithm is: ");
// displayArray(numbersForBuble, TOTAL_NUMBER, "sorted number using buble algorithm is:\n");
// 使用插入法得到第k个大的数
int kthNumber = insertAlgorithm(numbers,TOTAL_NUMBER,KTH);
printf("the k-th number computed by insert algorithm is: %d\n",kthNumber);
return 0;
}
实验结果,当数据量比较大时(TOTAL_NUMBER比较大),而KTH比较小时,显然时使用插入法的效率更高。
我在上面的程序中加入了计时功能,代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define TOTAL_NUMBER 500000
#define KTH (TOTAL_NUMBER/2)
//函数声明
void displayArray(int *data, int length, const char * preDisplay);
/*
* 产生指定数量的随机数
*/
int* generateIntergerArray(int totalNumber)
{
int* numberArray = (int *)malloc(sizeof(int)*totalNumber);
int i = 0;
for(i = 0; i<totalNumber; i++)
{
*(numberArray + i) = rand();
}
return numberArray;
}
/*
* 冒泡法对随机数组进行排序,从小到大
*/
int * bubleSort(int * data,int length)
{
int i = 0;
int j = 0;
// 变量i用来控制比较的范围,每次少比较右面的一个数,也就是最大的那个数
for(i = 0; i < length - 1; i++) //i:= 0,1,2...,length -2,一共length-1次比较
{
// 变量j用来对数组中的数逐个比较,j为索引
// 每次比较从第2个开始,到第length - i - 1个结束。当i=0时,data[length-1]就是最后一个数
for(j = 1; j <= length - i - 1; j++)
{
int temp = 0;
// 如果前一个数大于后一个数,那么这两个数互换。
if(*(data + j - 1) > *(data + j))
{
temp = *(data + j - 1);
*(data + j - 1) = *(data + j);
*(data + j) = temp;
}
}
// displayArray(data,length,"-------->");
}
return data;
}
/*
* 输出数组中的数
*/
void displayArray(int *data, int length,const char * preDisplay)
{
printf(preDisplay);
int i = 0;
for(i = 0;i < length; i++)
{
printf("%d,",*(data+i));
}
printf("\n\n");
}
/*
* 显示数组中的第k个数
*/
void displayKthElement(int *data, int k,const char * preDisplay)
{
printf(preDisplay);
printf("%d\n",*(data + k - 1));
}
/*
* 使用插入法,寻找第k个大的数
*/
int insertAlgorithm(int * data,int length, int kth)
{
assert(length >= kth);
// 建立长度为k的数组
int* kLengthArray = (int*)malloc(sizeof(int)*kth);
//将data中的前k个数读入kLengthArray中
int i = 0;
for(i = 0; i < kth; i++)
{
*(kLengthArray + i) = *(data + i);
}
// 使用冒泡法对kLengthArray进行排序
kLengthArray = bubleSort(kLengthArray, kth);
// displayArray(kLengthArray,kth,"the fist kLengthArray is: \n");
// 对剩下的数据进行插入
int count = kth; // 从第kth+1个数开始进行插入
int index = kth - 1; // 从右往左插入,即从第kth个数开始插入
for(count = kth; count <= length - 1; count++) // 使用第count个数进行比较,然后插入
{
// 得到插入的数在kLengthArray中的位置 index
for(index = kth - 1; index >= -1; index--)
{
if (*(data + count) > *(kLengthArray + index))
{
break;
}
}
// 如果index不能维持原值,那么存在一个数在kLengthArray的数的中间,需要进行插入操作
if (index != kth - 1)
{
int i = 0;
for(i = 0; i < kth - index - 2; i++)
{
*(kLengthArray + kth - i - 1) = *(kLengthArray + kth - i - 2);
}
*(kLengthArray + index + 1) = *(data + count);
}
}
// displayArray(kLengthArray,kth,"the final kLengthArray is: \n");
return *(kLengthArray + kth - 1);
}
int main()
{
int* numbers;
numbers = generateIntergerArray(TOTAL_NUMBER);
// displayArray(numbers, TOTAL_NUMBER, "random number generated is:\n");
clock_t timePointA = clock();
// 使用冒泡法得到第k个大的数
int * numbersForBuble = (int*)malloc(sizeof(int)*TOTAL_NUMBER);
numbersForBuble = bubleSort(numbers,TOTAL_NUMBER);
displayKthElement(numbersForBuble,KTH,"the k-th element computed by buble algorithm is: ");
clock_t timePointB = clock();
// displayArray(numbersForBuble, TOTAL_NUMBER, "sorted number using buble algorithm is:\n");
clock_t timePointC = clock();
// 使用插入法得到第k个大的数
int kthNumber = insertAlgorithm(numbers,TOTAL_NUMBER,KTH);
printf("the k-th number computed by insert algorithm is: %d\n",kthNumber);
printf("-----------------------------------------------------------------\n");
clock_t timePointD = clock();
printf("timePointB - timePointA = %d\n", timePointB - timePointA);
printf("timePointD - timePointC = %d\n", timePointD - timePointC);
printf("-----------------------------------------------------------------\n");
double timeOfBubleAlgorithm = (double)(timePointB - timePointA)/CLOCKS_PER_SEC;
double timeOfInsertAlgorithm = (double)(timePointD - timePointC)/CLOCKS_PER_SEC;
printf("the time buble algorithm use is: %f s\n", timeOfBubleAlgorithm);
printf("the time insert algorithm use is: %f s\n", timeOfInsertAlgorithm);
return 0;
}
当TOTAL_NUMBER为500000时,冒泡法需要838.66秒,插入法需要89.5秒。没有书上说的需要几天,可能是现在的计算机计算的快了吧。
当TOTAL_NUMBER为100000时,冒泡法需要33.3秒,插入法需要3.63秒。
当TOTAL_NUMBER为20000时,冒泡法需要1.239秒,插入法需要0.148秒。
当TOTAL_NUMBER为4000时,冒泡法需要0.037秒,插入法需要0.007秒。
当TOTAL_NUMBER为800时,冒泡法需要0.02秒,插入法需要0.001秒。
当TOTAL_NUMBER为160时,冒泡法需要0.01秒,插入法需要0.000秒(程序是这样显示,显然是不可能的,也许超出计程序的精度了吧)。
当TOTAL_NUMBER为32时,冒泡法需要0.0000秒,插入法需要0.0000秒,程序是这样显示,显然是不可能的,也许超出计程序的精度了吧)。