《數據結構與算法分析:C語言描述》習題1.1
大一狗放假在家自學點算法,編程渣,自己練習一下
————————————————————————————————————————(我是劃分線)
題目:編寫一個程序解決選擇問題。令k=N/2。畫出表格顯示你的程序對於N為不同值的運行時間。
先來解釋一下什麼是“選擇問題”:設有一組N個數而要確定其中第k個最大者。
書上第一章一開始就講了一種算法。
再次闡述一下:
先把前面k個數讀進一個數組中並(以遞減的順序)對其排序(排序後下標為[0]的為最大數,下標為[k-1]的為k個數中的最小數)。接著,將剩下的元素再逐個讀入。當新元素被讀到時,如果它小於數組中的第k個元素(下標為[k-1])則忽略,否則就將其放到數組中正確的位置上,同時將數組中的一個元素擠出數組。當算法結束時,位於第k個位置上的元素作為答案返回。
一开始我是在main函數裡寫的,寫完後想想還是改寫成一個函數了。於是複製粘貼。。。
下面是我的代碼:
#include <cstdio>
#include <ctime>
float ChooseK(const float A[], int n);
int main()
{
double t; //时间变量
clock_t start,end; //用于计时
int n, i;
float result;
printf("how many numbers you want to put in?\n");
scanf("%d",&n); //设置数的总数
float arr[n/2]; //能盛放前k个数的数组
for (i=0; i<n/2; i++)
scanf("%f",&arr[i]);
start=clock(); //计时开始
result = ChooseK(arr, n);
end=clock(); //计时结束
t=((double)(end-start))/CLOCKS_PER_SEC; //计算总时长
printf("\n第k个最大的数字是%.2f\n", result); //输出第k个最大者
printf("The choosing program use %.7lf\n",t); //输出用时
return 0;
}
float ChooseK(const float A[], int n)
{
int k = n/2;
float arr[k];
int i,j; //计数变量
float temp; //用于排序的交换
for (i = 0; i < k ; i++) //转移数组,方便数据交换
arr[i] = A[i];
for (i=1; i<k; i++) //冒泡排序法对前面k个数进行降序排序
{
for (j=0; j<k-i; j++)
{
if(arr[j]<arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
float new; //用于读取第k个以后的数字
for ( k=1+n/2 ; k <= n ; k++)
{
scanf("%f",&new);
if (new <= arr[n/2-1])
continue;
else
{
i=n/2-1;
while (new>arr[i]) //找到new的正确位置
{
i--;
if (i<0)
break;
}
int place = i+1;
for (i=n/2-1; i > place; i--) //删除的一定是最后一个数,然后依次向后移一位
arr[i] = arr[i-1];
arr[place] = new;
}
}
return arr[n/2-1]; //返回数组中的第k个元素(数组中的最小数)
}
注意一下將new插入數組的過程。一開始我是從定位得到的arr[place]依次向後交換數值,這樣一來,每一次兩個數交換實際涉及三個變量,分別是arr[i],arr[i+1]和中間變量(現在已經改掉了,我發的代碼裡沒有這一變量),這樣可能會降低效率。=====於是~我後來改了一種,就是從後向前改動數。因為每一次插入一個新的數,被擠出數組的永遠是最後一個數,這樣就沒必要在向後移動其他數據的時候仍舊保留最後一個數,所以可以直接讓最後一個數賦值為倒數第二個數,倒數第二個數賦值為倒數第三個數,依次向前推進直到要插入新數據的位置處停止,然後將新的數據new放到指定位置。