思考题8-1
a)
n
个不同元素一共有
b) 当
k>1
时说明根结点
T
不是叶结点,意味着
证明:设
c) 要证明结论,只需分别证明 d(k)≥min1≤x≤k−1{d(i)+d(k−i)+k} 和 d(k)≤min1≤x≤k−1{d(i)+d(k−i)+k} 即可。
证明
d(k)≥min1≤x≤k−1{d(i)+d(k−i)+k}
,只要证明对
i=1,2…k−1
有
d(k)≥d(i)+d(k−i)+k
。我们拿走
T
和
证明 d(k)≤min1≤x≤k−1{d(i)+d(k−i)+k} ,只要证明对 i=1,2…k−1 有 d(k)≤d(i)+d(k−i)+k 。对任意 i 属于
因此得证。
d)
因而在 i=k2 得到最小值。用归纳法证明 d(k)=Ω(klgk) 。
d(1)≥0=c⋅1⋅lg1 对任意 c 成立 。设对
得证。
e) TA 有 n! 个叶结点,所以 D(n)>d(k)=Ω(n!lg(n!)) 。每种排序的概率为 1/n! ,因此期望运行时间:
f) 为了构建和
B
相对应确定算法
思考题8-2
a) 计数排序。
b) 快排中的PARTITION
即可实现。
c) 冒泡排序、插入排序都可。
d) 基数排序需要使用稳定的排序方法,因此必须满足条件2。所以只有计数排序可以。
e) 给一个简单的方法。我们先统计每个记录出现的次数,然后直接放入数组中,举例
1,3,2,3,1,1,2,
,
COUNT
数组中分别是
COUNT[1]=3,COUNT[2]=2,COUNT[3]=2
。然后数组
A[0−2]=1,A[3−4]=2,A[5−6]=3
。
显然这个是不稳定的。
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
void COUNT_SORT(int *array,int length,int max_int_k)
{
int *C = new int[max_int_k+1];
memset(C,0,sizeof(int)*(max_int_k+1));
for(int i = 0; i < length; ++i)
++C[array[i]];
int cnt = 0;
for(int i = 1; i <= max_int_k; ++i)
{
while(C[i] > 0)
{
array[cnt++] = i;
--C[i];
}
}
delete []C;
}
int main()
{
int ia[] = {1,3,2,3,1,1,2,7};
COUNT_SORT(ia,8,7);
for(int i = 0; i < 8; ++i)
cout << ia[i] << ' ';
cout << endl;
return 0;
}
思考题8-3
a) 首先假设全部是整数并且数字没有前导
0
,即没有
设数字位数为
i
的有
b) 将首字母相同的分成一组,使用计数排序第一个字母;若第一个字母相同,则去掉首字母再分组,递归排序直到只有一个字母。需要注意的是长度为
l
的字符串可能需要
思考题8-4
a) 很简单,比较每个红色和蓝色水壶,即暴力破解,总时间 Θ(n2) 。
b) 类似决策树模型,结点内部是要比较的两个水壶,比较结果引出三条边,红色大于蓝色、等于蓝色、小于蓝色。叶结点就是匹配的水壶。
n
个红色和蓝色水壶一共有
c)
1.随机选一个红色水壶
O(1)
;
2.找出对应的蓝色水壶
O(n)
;
3.挑出的红色水壶在和蓝色组水壶对比时,蓝色水壶就可以分成两组(可能一组为空);
4.类似 3,步骤 2 选出的蓝色水壶对比红色组,红色水壶分成两组;
5.分别递归划分的两组水壶。显然期望比较次数
O(nlgn)
,最坏情况下是
O(n2)
。
下面的代码用两组数字代表两种颜色不同大小的水壶,最后排序两组数表示配对成功。
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
int partition(int *red,int *blue,int p,int r)
{
int index_red = rand() % (r - p + 1) + p;
int index_blue;
//找出红色对于的蓝色的下标
for(index_blue = p; index_blue <= r; ++index_blue)
{
if(red[index_red] == blue[index_blue])
break;
}
//交换blue的piovt
int temp = blue[index_blue];
blue[index_blue] = blue[r];
blue[r] = temp;
//划分blue
int i = p - 1;
int blue_pivot = red[index_red];//蓝色不能和蓝色的水壶比较,所以此处用的红色
for(int j = p; j < r; ++j)
{
if(blue[j] <= blue_pivot)
{
++i;
temp = blue[j];
blue[j] = blue[i];
blue[i] = temp;
}
}
temp = blue[r];
blue[r] = blue[i+1];
blue[i+1] = temp;
//交换red的piovt
temp = red[index_red];
red[index_red] = red[r];
red[r] = temp;
//划分red
int k = p - 1;
int red_piovt = blue[i+1];
for(int j = p; j < r; ++j)
{
if(red[j] <= red_piovt)
{
++k;
temp = red[j];
red[j] = red[k];
red[k] = temp;
}
}
temp = red[r];
red[r] = red[k+1];
red[k+1] = temp;
//返回划分的下标
return k + 1;
}
void match_jugs(int *red,int *blue,int p,int r)
{
if(p < r)
{
int q = partition(red,blue,p,r);
match_jugs(red,blue,p,q-1);
match_jugs(red,blue,q+1,r);
}
}
int main()
{
int ia[] = {13,-3,-25,20,-16,-23,18};
int ib[] = {18,20,-3,-23,13,-16,-25};
match_jugs(ia,ib,0,6);
for(int i = 0; i < 7; ++i)
cout << ia[i] << ' ';
cout << endl;
for(int i = 0; i < 7; ++i)
cout << ib[i] << ' ';
cout << endl;
return 0;
}
思考题8-5
a) 就是普通的排序。
b) 2,1,4,3,6,5,8,7,10,9 .
c)证明:
d) 由 c) 的证明,可以将数组分成
k
组,即
e) 和练习 6.5-9 十分类似,建一个堆,运行时间是 O(nlgk) (参考6.5-9)。
f) 一共
k
组,每组
思考题8-6
a)
2n
个数中选
n
个,即
b) 首先
(2nn)=22nπn√(1+O(1/n))
,根据决策树模型,设有
l
个叶子结点,树高
化简有:
c) 很明显,不比较怎么知道哪个元素出列。
d) 对元素 ⟨a1,b2,a2,b2,…,an,bn⟩ 分成子表 ⟨a1,a2,…,an⟩ 和 ⟨b1,b2,…,bn⟩ ,一共有 2n−1 对元素需要比较,所以需要比较 2n−1 次。
思考题8-7
题目出奇的长,实在不想看,附一个链接,答案见此处这里写链接内容