第三章
PE03
/**********
【题目】试以顺序表L的L.rcd[L.length+1]作为监视哨,
改写教材3.2节中给出的升序直接插入排序算法。
顺序表的类型RcdSqList定义如下:
typedef struct {
KeyType key;
…
} RcdType;
typedef struct {
RcdType rcd[MAXSIZE+1]; // rcd[0]闲置
int length;
} RcdSqList;
**********/
void InsertSort(RcdSqList &L)
{
int i,j;
for(i=1;i<L.length;i++){
if(L.rcd[i+1].key<L.rcd[i].key){
L.rcd[L.length+1].key=L.rcd[i+1].key;
j=i+1;
do{
j--;
L.rcd[j+1].key=L.rcd[j].key;
}while(L.rcd[L.length+1].key<L.rcd[j-1].key);
L.rcd[j].key=L.rcd[L.length+1].key;
}
}
}
PE06
/**********
【题目】如下所述,改写教材1.3.2节例1-10的冒泡排序算法:
将算法中用以起控制作用的布尔变量change改为一个整型
变量,指示每一趟排序中进行交换的最后一个记录的位置,
并以它作为下一趟起泡排序循环终止的控制值。
顺序表的类型RcdSqList定义如下:
typedef struct {
KeyType key;
…
} RcdType;
typedef struct {
RcdType rcd[MAXSIZE+1]; // rcd[0]闲置
int length;
} RcdSqList;
**********/
void BubbleSort(RcdSqList &L)
/* 元素比较和交换必须调用如下定义的比较函数和交换函数:*/
/* Status LT(RedType a, RedType b); 比较:"<" */
/* Status GT(RedType a, RedType b); 比较:">" */
/* void Swap(RedType &a, RedType &b); 交换 */
{
int i,j,change=1;
for(i=L.length;i>1&&change;i=change){
change=0;
for(j=1;j<i;j++)
if(GT(L.rcd[j],L.rcd[j+1])){
Swap(L.rcd[j],L.rcd[j+1]);
change=j;
}
}
}
PE23
/**********
【题目】已知记录序列L.rcd[1…L.length]中的关键
字各不相同,可按如下所述实现计数排序:另设数组
c[1…n],对每个记录a[i], 统计序列中关键字比它
小的记录个数存于c[i],则c[i]=0的记录必为关键字
最小的记录,然后依c[i]值的大小对序列中记录进行
重新排列。试编写算法实现上述排序方法。
顺序表的类型RcdSqList定义如下:
typedef struct {
KeyType key;
…
} RcdType;
typedef struct {
RcdType rcd[MAXSIZE+1]; // rcd[0]闲置
int length;
} RcdSqList;
**********/
void CountSort(RcdSqList &L)
/* 采用顺序表存储结构,在函数内自行定义计数数组c */
{
int i,j,count;
KeyType *rcd2;
if(L.length!=0){
rcd2=(KeyType *)malloc(L.length * sizeof(KeyType));
for(j=0;j<L.length;j++)
rcd2[j]=0;
for(i=1;i<L.length+1;i++){
count = 0;
for(j=1;j<L.length+1;j++)
if(L.rcd[j].key<L.rcd[i].key)
count++;
while(rcd2[count]!=0) //如果出现相同数据就后移一位
count++;
rcd2[count]=L.rcd[i].key;
}
//在rcd2中数据是从0开始存放的,在L.rcd中是从1开始
for(i=0;i<L.length;i++)
L.rcd[i+1].key=rcd2[i];
free(rcd2);
}
}
第四章
PE04
/**********
【题目】已知某哈希表的装载因子小于1,哈希函数H(key)
为关键字(标识符)的第一个字母在字母表中的序号,处理
冲突的方法为线性探测开放定址法。试编写一个按第一个
字母的顺序输出哈希表中所有关键字的算法。
哈希表的类型HashTable定义如下:
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
typedef char StrKeyType[4];
typedef struct {
StrKeyType key; // 关键字项
int tag; // 标记 0:空;1:有效; -1:已删除
void *any; // 其他信息
} RcdType;
typedef struct {
RcdType *rcd; // 存储空间基址
int size; // 哈希表容量
int count; // 表中当前记录个数
} HashTable;
**********/
void PrintKeys(HashTable ht, void(*print)(StrKeyType))
/* 依题意用print输出关键字 */
{
int n,i;
for(char c = 'A';c<='Z';c++){
n = (c-'A')%ht.size;
i = n;
while((n+1)%ht.size!=i){
if(ht.rcd[n].tag!=-1 && ht.rcd[n].key[0]==c){
print(ht.rcd[n].key);
break;
}
n=(n+1)%ht.size;
}
}
}
PE15
/**********
【题目】假设哈希表长为m,哈希函数为H(x),用链地址法
处理冲突。试编写输入一组关键字并建造哈希表的算法。
哈希表的类型ChainHashTab定义如下:
#define NUM 7
#define NULLKEY -1
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
typedef char HKeyType;
typedef struct HNode {
HKeyType data;
struct HNode* next;
}*HLink;
typedef struct {
HLink *rcd; // 指针存储基址,动态分配数组
int count; // 当前表中含有的记录个数
int size; // 哈希表的当前容量
}ChainHashTab; // 链地址哈希表
int Hash(ChainHashTab H, HKeyType k) { // 哈希函数
return k % H.size;
}
Status Collision(ChainHashTab H, HLink &p) {
// 求得下一个探查地址p
if (p && p->next) {
p = p->next;
return SUCCESS;
} else return UNSUCCESS;
}
**********/
int BuildHashTab(ChainHashTab &H, int n, HKeyType es[])
/* 直接调用下列函数 */
/* 哈希函数: */
/* int Hash(ChainHashTab H, HKeyType k); */
/* 冲突处理函数: */
/* int Collision(ChainHashTab H, HLink &p); */
{
int i,p,flag;
HLink np,t;
H.rcd=(HLink*)malloc(NUM*sizeof(HLink));
if(NULL==H.rcd)
return UNSUCCESS;
for(i=0;i<NUM;i++)
H.rcd[i]=NULL;
H.size=NUM;
H.count=0;
for(i=0;i<n;i++){
flag=0;
p=Hash(H,es[i]);
t=H.rcd[p];
do{
if(es[i]==t->data){
flag=-1; break;
}
}while(Collision(H,t));
if(flag==0){
np=(HLink)malloc(sizeof(HNode));
if(NULL==np)
return UNSUCCESS;
np->data=es[i];
np->next=H.rcd[p];
H.rcd[p]=np;
Collision(H,np);
H.count++;
}
}
}
第五章
PE04
/**********
【题目】试编写如下定义的递归函数的递归算法:
g(m,n) = 0 当m=0,n>=0
g(m,n) = g(m-1,2n)+n 当m>0,n>=0
**********/
int G(int m, int n)
/* 如果 m<0 或 n<0 则返回 -1 */
{
if(m>=0&&n>=0){
if(m==0)
return 0;
else
return G(m-1,2*n)+n;
}
else return -1;
}
PE05
/**********
【题目】试写出求递归函数F(n)的递归算法:
F(n) = n+1 当n=0
F(n) = nF(n/2) 当n>0
**********/
int F(int n)
/* 如果 n<0 则返回 -1 */
{
if(n>=0){
if(n==0)
return n+1;
else
return n*F(n/2);
}
else return -1;
}
PE06
/**********
【题目】求解平方根 的迭代函数定义如下:
sqrt(A,p,e) = p 当|pp-A|<e
sqrt(A,p,e) = sqrt(A,(p+A/p)/2,e) 当|pp-A|>=e
其中,p是A的近似平方根,e是结果允许误差。试写出相
应的递归算法。
**********/
float Sqrt(float A, float p, float e)
{
if((p*p-A)*(p*p-A)<e*e)
return p;
return Sqrt(A,(p+A/p)/2,e);
}
PE07
【题目】已知Ackerman函数的定义如下:
akm(m,n) = n+1 当m=0
akm(m,n) = akm(m-1,1) 当m!=0,n=0
akm(m,n) = akm(m-1,akm(m,n-1)) 当m!=0,n!=0
请写出递归算法。
**********/
int Akm(int m, int n)
/* 若 m<0 或 n<0 则返回-1 */
{
if(m<0||n<0)
return -1;
if(m==0)
return n+1;
else if(n==0)
return Akm(m-1,1);
else
return Akm(m-1,Akm(m,n-1));
}
PE15
/**********
【题目】试写出求递归函数F(n)的非递归算法:
F(n) = n+1 当n=0
F(n) = nF(n/2) 当n>0
**********/
int F(int n)
/* 如果 n<0 则返回 -1 */
{
int S=1;
if(n<0)
return -1;
if(n==0)
return 1;
while(n>0){
S*=n;
n/=2;
}
return S;
}
/*
{ //递归
if(n<0)
return -1;
if(n==0)
return 1;
return n*F(n/2);
}
*/
PE16
/**********
【题目】求解平方根 的迭代函数定义如下:
sqrt(A,p,e) = p 当|pp-A|<e
sqrt(A,p,e) = sqrt(A,(p+A/p)/2,e) 当|pp-A|>=e
其中,p是A的近似平方根,e是结果允许误差。试写出相
应的非递归算法。
**********/
float Sqrt(float A, float p, float e)
{
if((p*p-A)*(p*p-A)<e*e)
return p;
while((p*p-A)*(p*p-A)>=e*e){
p=(p+A/p)/2;
}
return p;
}
/*
{ //递归
if((p*p-A)*(p*p-A)<e*e)
return p;
return Sqrt(A,(p+A/p)/2,e);
}
*/
PE20
/**********
【题目】假设以二维数组g[1…m][1…n]表示一个图像
区域,g[i][j]表示该区域中点(i,j)所具颜色,其值
为从0到k的整数。试编写递归算法,将点(i0,j0)所在
区域的颜色置换为颜色c。约定与(i0,j0)同色的上、
下、左、右的邻接点为同色区域的点。
表示图像区域的类型定义如下:
typedef char GTYPE[m+1][n+1];
**********/
void ChangeColor(GTYPE g, int m, int n,
char c, int i0, int j0)
/* 在g[1..m][1..n]中,将元素g[i0][j0] */
/* 所在的同色区域的颜色置换为颜色c */
{
char color=g[i0][j0];
g[i0][j0]=c;
if(i0-1>=1&&g[i0-1][j0]==color)
ChangeColor(g,m,n,c,i0-1,j0);
if(j0-1>=1&&g[i0][j0-1]==color)
ChangeColor(g,m,n,c,i0,j0-1);
if(i0+1<=m&&g[i0+1][j0]==color)
ChangeColor(g,m,n,c,i0+1,j0);
if(j0+1<=n&&g[i0][j0+1]==color)
ChangeColor(g,m,n,c,i0,j0+1);
}
PE30
/**********
【题目】试按依次对每个元素递归分解的分析方法重写求广义表的深度的递归算法。
广义表类型GList的定义:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
**********/
int GListDepth(GList ls)
/* Return the depth of list */
{
int h1,h2;
if(NULL==ls)
return 1;
if(ATOM==ls->tag)
return 0;
h1 = GListDepth(ls->un.ptr.hp)+1;
h2 = GListDepth(ls->un.ptr.tp);
return h1>=h2?h1:h2;
}
PE32
/**********
【题目】试编写判别两个广义表是否相等的递归算法。
广义表类型GList的定义:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
**********/
Status Equal(GList A, GList B)
/* 判断广义表A和B是否相等,是则返回TRUE,否则返回FALSE */
{
if(A==NULL&&B==NULL)
return TRUE; //如果是空表
else if(A==NULL||B==NULL||A->tag!=B->tag)
return FALSE; //表的类型不一样
else if(A->tag==ATOM&&A->un.atom==B->un.atom)
return TRUE; //原子结点的内容不一样
if(Equal(A->un.ptr.hp,B->un.ptr.hp)&&Equal(A->un.ptr.tp,B->un.ptr.tp))
return TRUE; //如果是表结点类型,递归判断
else return FALSE;
}
PE33
/**********
【题目】试编写递归算法,输出广义表中所有原子项及其所在层次。
广义表类型GList的定义:
typedef enum {ATOM,LIST} ElemTag;
typedef struct GLNode{
ElemTag tag;
union {
char atom;
struct {
GLNode *hp, *tp;
} ptr;
}un;
} *GList;
**********/
void OutAtom(GList A, int layer, void(*Out2)(char, int))
/* 递归地用函数Out2输出广义表的原子及其所在层次,layer表示当前层次 */
{
if(A){
if(A->tag==ATOM)
Out2(A->un.atom,layer);
else{
OutAtom(A->un.ptr.hp,layer+1,Out2);
OutAtom(A->un.ptr.tp,layer,Out2);
}
}
}