Anyview数据结构习题练习记录
欢迎加入Anyview项目组(哈哈
踩过的坑:
- 条件判断需注意特殊情况(尤其对 FALSE/ERROR 的
- 注意已定义的类型(经常把 S.top 写成 top
- 注意题目需要mallloc还是realloc
- 貌似不能一行写完定义+malloc 偶尔会编译不通过 只能这样
int *t;
t = (int *)malloc(sizeof(int));
- 循环队列要注意 front 和 rear 不要搞混 以及判空判满
第六第七章树是真的烦…建议先做第八章的图
DC01
PE06
/**********
【题目】试写一算法,如果三个整数a,b和c的值
不是依次非递增的,则通过交换,令其为非递增。
***********/
void swap(int &i,int &j)
{
int temp;
temp=i;
i=j;
j=temp;
}
void Descend(int &a, int &b, int &c)
/* 通过交换,令 a >= b >= c */
{
if(a<b)
swap(a,b);
if(b<c)
swap(b,c);
if(a<b)
swap(a,b);
}
PE08
/**********
【题目】试编写算法求一元多项式
P(x) = a0 + a1x + a2x^2 + ... + anx^n
的值P(x0),并确定算法中每一语句的执行次数和整个算法
的时间复杂度。
**********/
float Polynomial(int n, int a[], float x)
/* 求一元多项式的值P(x)。 */
/* 数组a的元素a[i]为i次项的系数,i=0,...,n */
{
float res = 0;
int i = 0;
float t = 1;
for(;i<=n;i++)
{
res+=a[i]*t;
t*=x;
}
return res;
}
PE11
/**********
【题目】已知k阶裴波那契序列的定义为
f(0)=0, f(1)=0, ..., f(k-2)=0, f(k-1)=1;
f(n)=f(n-1)+f(n-2)+...+f(n-k), n=k,k+1,...
试编写求k阶裴波那契序列的第m项值的函数算法,
k和m均以值调用的形式在函数参数表中出现。
**********/
Status Fibonacci(int k, int m, int &f)
/* 求k阶斐波那契序列的第m项的值f */
{
if(k<=1||m<0)
return ERROR;
if(m<k-1)
{
f=0;
return OK;
}
else if(m==k-1)
{
f=1;
return OK;
}
int res[500]={0};
res[k-1]=1;
for(int i=k;i<=m;i++)
{
int t=0;
for(int j=i-k;j>=0&&j<i;j++)
t+=res[j];
res[i]=t;
}
f= res[m];
return OK;
}
PE18
/**********
【题目】试编写算法,计算i!×2^i的值并存入数组
a[0..n-1]的第i-1个分量中 (i=1,2,…,n)。假设计
算机中允许的整数最大值为MAXINT,则当对某个k
(1≤k≤n)使k!×2^k>MAXINT时,应按出错处理。注意
选择你认为较好的出错处理方法。
**********/
Status Series(int a[], int n)
/* 求i!*2^i序列的值并依次存入长度为n的数组a; */
/* 若所有值均不超过MAXINT,则返回OK,否则OVERFLOW */
{
int t1=1;
int t2=2;
int i=1;
for(;i<=n;i++)
{
a[i-1]=t1*t2;
if(a[i-1]<0||a[i-1]>MAXINT)
return OVERFLOW;
t1*=i+1;
t2<<=1;
}
return OK;
}
PE23
【题目】假设有A、B、C、D、E五个高等院校进行田径对抗赛,
各院校的单项成绩均以存入计算机并构成一张表,表中每一行
的形式为:
项目名称 性别 校名 成绩 得分
编写算法,处理上述表格,以统计各院校的男、女总分和团体
总分,并输出。
要求实现下列函数:
void Scores(ResultType *result, ScoreType *score);
/* 求各校的男、女总分和团体总分, 并依次存入数组score */
/* 假设比赛结果已经储存在result[ ]数组中, */
/* 并以特殊记录 {"", male, ' ', "", 0 }(域scorce=0)*/
/* 表示结束 */
相关数据类型定义如下:
typedef enum {female,male} Sex;
typedef struct{
char *sport; // 项目名称
Sex gender; // 性别(女:female;男:male)
char schoolname; // 校名为'A','B','C','D'或'E'
char *result; // 成绩
int score; // 得分(7,5,4,3,2或1)
} ResultType;
typedef struct{
int malescore; // 男子总分
int femalescore; // 女子总分
int totalscore; // 男女团体总分
} ScoreType;
void Scores(ResultType *result,ScoreType *score){
for(int i = 0; result[i].sport != NULL ; i++){
int school = result[i].schoolname - 'A';
if(result[i].gender == female)
score[school].femalescore += result[i].score;
else score[school].malescore += result[i].score;
score[school].totalscore = score[school].femalescore + score[school].malescore;
}
PE46
/**********
【题目】试写一算法,对序列S的第i个元素赋以值e。
序列的类型定义为:
typedef struct {
ElemType *elem;
int length;
} Sequence;
***********/
Status Assign(Sequence &S, int i, ElemType e)
/* 对序列S的第i个元素赋以值e,并返回OK。 */
/* 若S或i不合法,则赋值失败,返回ERROR */
{
if(NULL == S.elem ||i>= S.length || i <0)
return ERROR;
S.elem[i] = e;
return OK;
}
PE49
/**********
【题目】试写一算法,由长度为n的一维数组a构建一个序列S。
序列的类型定义为:
typedef struct {
ElemType *elem;
int length;
} Sequence;
***********/
Status CreateSequence(Sequence &S, int n, ElemType *a)
/* 由长度为n的一维数组a构建一个序列S,并返回OK。 */
/* 若构建失败,则返回ERROR */
{
if(NULL == a || n <=0)
return ERROR;
else {
S.length = n;
S.elem = a;
}
return OK;
}
PE61
/**********
【题目】链表的结点和指针类型定义如下
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
试写一函数,构建一个值为x的结点。
***********/
LinkList MakeNode(ElemType x)
/* 构建一个值为x的结点,并返回其指针。*/
/* 若构建失败,则返回NULL。 */
{
LNode p;
p.data = x;
if(NULL != &p)
return &p;
else return NULL;
}
PE63
/**********
【题目】链表的结点和指针类型定义如下
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
试写一函数,构建长度为2且两个结点的值依次为x和y的链表。
**********/
LinkList CreateLinkList(ElemType x, ElemType y)
/* 构建其两个结点的值依次为x和y的链表。*/
/* 若构建失败,则返回NULL。 */
{
LNode p,q;
p.data = x;
p.next = &q;
q.data = y;
q.next = NULL;
if(&p == NULL || &q == NULL)
return NULL;
else return &p;
}
PE65
/**********
【题目】链表的结点和指针类型定义如下
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
试写一函数,构建长度为2的升序链表,两个结点的值
分别为x和y,但应小的在前,大的在后。
**********/
LinkList CreateOrdLList(ElemType x, ElemType y)
/* 构建长度为2的升序链表。 */
/* 若构建失败,则返回NULL。 */
{
LNode p,q;
if(x>y){
int t=x;
x=y;
y=t;
}
p.data = x;
p.next = &q;
q.data = y;
q.next = NULL;
if(&p == NULL || &q == NULL)
return NULL;
else return &p;
}
DC02
PE03
【题目】试写一算法,实现顺序栈的判空操作
StackEmpty_Sq(SqStack S)。
要求实现下列函数:
Status StackEmpty_Sq(SqStack S);
/* 对顺序栈S判空。 */
/* 若S是空栈,则返回TRUE;否则返回FALSE */
顺序栈的类型定义为:
typedef struct {
ElemType *elem; // 存储空间的基址
int top; // 栈顶元素的下一个位置,简称栈顶位标
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack; // 顺序栈
Status StackEmpty_Sq(SqStack S){
if(!S.top)
return TRUE;
else FALSE;
}
PE05
/**********
【题目】试写一算法,实现顺序栈的取栈顶元素操作
GetTop_Sq(SqStack S, ElemType &e)。
顺序栈的类型定义为:
typedef struct {
ElemType *elem; // 存储空间的基址
int top; // 栈顶元素的下一个位置,简称栈顶位标
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack; // 顺序栈
***********/
Status GetTop_Sq(SqStack S, ElemType &e)
/* 取顺序栈S的栈顶元素到e,并返回OK; */
/* 若失败,则返回ERROR。 */
{
if(S.elem == NULL || S.top == 0)
return ERROR;
else {
e = S.elem[S.top-1];
return OK;
}
}
PE07
/**********
【题目】试写一算法,实现顺序栈的出栈操作
Pop_Sq(SqStack &S, ElemType &e)。
顺序栈的类型定义为:
typedef struct {
ElemType *elem; // 存储空间的基址
int top; // 栈顶元素的下一个位置,简称栈顶位标
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack; // 顺序栈
***********/
Status Pop_Sq(SqStack &S, ElemType &e)
/* 顺序栈S的栈顶元素出栈到e,并返回OK;*/
/* 若失败,则返回ERROR。 */
{
if(S.elem == NULL || S.top == 0) {
return ERROR;
}else {
e = S.elem[S.top-1];
S.top--;
return OK;
}
}
PE11
/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
构建初始容量和扩容增量分别为size和inc的空顺序栈S。
typedef struct {
ElemType *elem; // 存储空间的基址
ElemType *top; // 栈顶元素的下一个位置
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack2;
***********/
Status InitStack_Sq2(SqStack2 &S, int size, int inc)
/* 构建初始容量和扩容增量分别为size和inc的空顺序栈S。*/
/* 若成功,则返回OK;否则返回ERROR。 */
{
if(size <= 0 || inc <= 0)
return ERROR;
S.size = size;
S.increment = inc;
S.elem = (ElemType *)malloc(sizeof(ElemType)*size);
S.top = S.elem;
if(S.elem == NULL || S.top == NULL)
return ERROR;
else {
return OK;
}
}
PE13
/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的判空操作。
typedef struct {
ElemType *elem; // 存储空间的基址
ElemType *top; // 栈顶元素的下一个位置
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack2;
***********/
Status StackEmpty_Sq2(SqStack2 S)
/* 对顺序栈S判空。 */
/* 若S是空栈,则返回TRUE;否则返回FALSE */
{
if(S.top == S.elem) {
return TRUE;
}else {
return FALSE;
}
}
PE15
/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的入栈操作。
typedef struct {
ElemType *elem; // 存储空间的基址
ElemType *top; // 栈顶元素的下一个位置
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack2;
***********/
Status Push_Sq2(SqStack2 &S, ElemType e)
/* 若顺序栈S是满的,则扩容,若失败则返回ERROR。*/
/* 将e压入S,返回OK。 */
{
if(S.top == &S.elem[S.size-1]){
S.elem = (ElemType*)realloc(S.elem,sizeof(ElemType)*(S.size + S.increment));
if(S.elem == NULL)
return ERROR;
S.top = &S.elem[S.size-1];
S.size += S.increment;
}
*(S.top) = e;
S.top++;
return OK;
}
PE17
/**********
【题目】若顺序栈的类型重新定义如下。试编写算法,
实现顺序栈的出栈操作。
typedef struct {
ElemType *elem; // 存储空间的基址
ElemType *top; // 栈顶元素的下一个位置
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack2;
***********/
Status Pop_Sq2(SqStack2 &S, ElemType &e)
/* 若顺序栈S是空的,则返回ERROR; */
/* 否则将S的栈顶元素出栈到e,返回OK。*/
{
if(S.top == S.elem)
return ERROR;
else {
e = *(S.top-1);
S.top--;
return OK;
}
}
PE19
/**********
【题目】试写一算法,借助辅助栈,复制顺序栈S1得到S2。
顺序栈的类型定义为:
typedef struct {
ElemType *elem; // 存储空间的基址
int top; // 栈顶元素的下一个位置,简称栈顶位标
int size; // 当前分配的存储容量
int increment; // 扩容时,增加的存储容量
} SqStack; // 顺序栈
可调用顺序栈接口中下列函数:
Status InitStack_Sq(SqStack &S, int size, int inc); // 初始化顺序栈S
Status DestroyStack_Sq(SqStack &S); // 销毁顺序栈S
Status StackEmpty_Sq(SqStack S); // 栈S判空,若空则返回TRUE,否则FALSE
Status Push_Sq(SqStack &S, ElemType e); // 将元素e压入栈S
Status Pop_Sq(SqStack &S, ElemType &e); // 栈S的栈顶元素出栈到e
***********/
Status CopyStack_Sq(SqStack S1, SqStack &S2)
/* 借助辅助栈,复制顺序栈S1得到S2。 */
/* 若复制成功,则返回TRUE;否则FALSE。 */
{
SqStack temp;
InitStack_Sq(temp, S1.size, S1.increment);
InitStack_Sq(S2, S1.size, S1.increment);
if(temp.elem == NULL || S2.elem == NULL)
return FALSE;
while(!StackEmpty_Sq(S1)){
ElemType t;
Pop_Sq(S1, t);
Push_Sq(temp, t);
}
while(!StackEmpty_Sq(temp)){
ElemType t;
Pop_Sq(temp, t);
Push_Sq(S2, t);
}
DestroyStack_Sq(temp);
return TRUE;
}
PE23
/**********
【题目】试写一算法,求循环队列的长度。
循环队列的类型定义为:
typedef struct {
ElemType *base; // 存储空间的基址
int front; // 队头位标
int rear; // 队尾位标,指示队尾元素的下一位置
int maxSize; // 最大长度
} SqQueue;
***********/
int QueueLength_Sq(SqQueue Q)
/* 返回队列Q中元素个数,即队列的长度。 */
{
int res = (Q.rear - Q.front + Q.maxSize)% Q.maxSize;
return res;
}
PE25
/**********
【题目】如果希望循环队列中的元素都能得到利用,
则可设置一个标志域tag,并以tag值为0或1来区分尾
指针和头指针值相同时的队列状态是"空"还是"满"。
试编写与此结构相应的入队列和出队列的算法。
本题的循环队列CTagQueue的类型定义如下:
typedef struct {
ElemType elem[MAXQSIZE];
int tag;
int front;
int rear;
} CTagQueue;
**********/
Status EnCQueue(CTagQueue &Q, ElemType x)
/* 将元素x加入队列Q,并返回OK;*/
/* 若失败,则返回ERROR。 */
{
if(Q.rear == Q.front && Q.tag == 1)
return ERROR;
Q.elem[Q.rear] = x;
Q.rear = (Q.rear+1)%MAXQSIZE;
if(Q.rear == Q.front)
Q.tag = 1;
return OK;
}
Status DeCQueue(CTagQueue &Q, ElemType &x)
/* 将队列Q的队头元素退队到x,并返回OK;*/
/* 若失败,则返回ERROR。 */
{
if(Q.rear == Q.front && Q.tag == 0)
return ERROR;
x = Q.elem[Q.front];
Q.front = (Q.front+1)%MAXQSIZE;
if(Q.rear == Q.front)
Q.tag = 0;
return OK;
}
PE27
/**********
【题目】假设将循环队列定义为:以域变量rear
和length分别指示循环队列中队尾元素的位置和内
含元素的个数。试给出此循环队列的队满条件,并
写出相应的入队列和出队列的算法(在出队列的算
法中要返回队头元素)。
本题的循环队列CLenQueue的类型定义如下:
typedef struct {
ElemType elem[MAXQSIZE];
int length;
int rear;
} CLenQueue;
**********/
Status EnCQueue(CLenQueue &Q, ElemType x)
/* 将元素x加入队列Q,并返回OK;*/
/* 若失败,则返回ERROR。 */
{
if(MAXQSIZE == Q.length)
return ERROR;
else{
Q.rear = (Q.rear+1)%MAXQSIZE;
Q.elem[Q.rear] = x;
Q.length++;
}
return OK;
}
Status DeCQueue(CLenQueue &Q, ElemType &x)
/* 将队列Q的队头元素退队到x,并返回OK;*/
/* 若失败,则返回ERROR。 */
{
if(!Q.length)
return ERROR;
else {
int front = (Q.rear +1 - Q.length + MAXQSIZE)%MAXQSIZE;
x = Q.elem[front];
Q.length--;
}
return OK;
}
PE53
/**********
【题目】试写一算法,实现链栈的判空操作。
链栈的类型定义为:
typedef struct LSNode {
ElemType data; // 数据域
struct LSNode *next; // 指针域
} LSNode, *LStack; // 结点和链栈类型
***********/
Status StackEmpty_L(LStack S)
/* 对链栈S判空。若S是空栈,则返回TRUE;否则返回FALSE */
{
if(S == NULL)
return TRUE;
else return FALSE;
}```
## PE55
```cpp
/**********
【题目】试写一算法,实现链栈的取栈顶元素操作。
链栈的类型定义为:
typedef struct LSNode {
ElemType data; // 数据域
struct LSNode *next; // 指针域
} LSNode, *LStack; // 结点和链栈类型
***********/
Status GetTop_L(LStack S, ElemType &e)
/* 取链栈S的栈顶元素到e,并返回OK; */
/* 若S是空栈,则失败,返回ERROR。 */
{
if(S == NULL)
return ERROR;
e = S->data;
return OK;
}
PE61
/**********
【题目】试写一算法,实现链队列的判空操作。
链队列的类型定义为:
typedef struct LQNode {
ElemType data;
struct LQNode *next;
} LQNode, *QueuePtr; // 结点和结点指针类型
typedef struct {
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LQueue; // 链队列类型
***********/
Status QueueEmpty_LQ(LQueue Q)
/* 判定链队列Q是否为空队列。 */
/* 若Q是空队列,则返回TRUE,否则FALSE。*/
{
if(Q.front == NULL && Q.rear == NULL)
return TRUE;
else return FALSE;
}
PE63
/**********
【题目】试写一算法,实现链队列的求队列长度操作。
链队列的类型定义为:
typedef struct LQNode {
ElemType data;
struct LQNode *next;
} LQNode, *QueuePtr; // 结点和结点指针类型
typedef struct {
QueuePtr front; // 队头指针
QueuePtr rear; // 队尾指针
} LQueue; // 链队列类型
***********/
int QueueLength_LQ(LQueue Q)
/* 求链队列Q的长度并返回其值 */
{
if(Q.rear == NULL && Q.front == NULL)
return 0;
int length = 1;
LQNode *p = Q.front;
while(p != Q.rear){
length++;
p = p->next;
}
return length;
}
PE68
/**********
【题目】假设以带头结点的循环链表表示队列,并且
只设一个指针指向队尾元素结点(注意不设头指针),
试编写相应的队列初始化、入队列和出队列的算法。
带头结点循环链队列CLQueue的类型定义为:
typedef struct LQNode {
ElemType data;
struct LQNode *next;
} LQNode, *CLQueue;
**********/
Status InitCLQueue(CLQueue &rear) // 初始化空队列
{
rear=(CLQueue)malloc(sizeof(LQNode));
if(rear == NULL)
return ERROR;
rear->next=rear;
return OK;
}
Status EnCLQueue(CLQueue &rear, ElemType x) // 入队
{
LQNode *t;
t = (LQNode*)malloc(sizeof(LQNode));
if(rear->next == NULL)
return ERROR;
t->data = x;
t->next = rear->next;
rear->next = t;
rear = t;
return OK;
}
Status DeCLQueue(CLQueue &rear, ElemType &x) // 出队
{
if(rear->next == rear)
return ERROR;
LQNode *front = rear->next;
LQNode *p = front->next;
front->next = p->next;
x = p->data;
free(p);
return OK;
}
PE71
/**********
【题目】试写一算法,实现带头结点单链表的判空操作。
单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList; // 结点和结点指针类型
***********/
Status ListEmpty_L(LinkList L)
/* 判定带头结点单链表L是否为空链表。 */
/* 若L是空链表,则返回TRUE,否则FALSE。*/
{
if(L->next == NULL)
return TRUE;
else return FALSE;
}
PE73
/**********
【题目】试写一算法,实现带头结点单链表的销毁操作。
单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList; // 结点和结点指针类型
***********/
Status DestroyList_L(LinkList &L)
/* 销毁带头结点单链表L,并返回OK。*/
{
LNode *p = L;
LNode *t;
while(p!=NULL){
t = p;
p = p->next;
free(t);
}
L = NULL;
return OK;
}
PE75
/**********
【题目】试写一算法,实现带头结点单链表的清空操作。
单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList; // 结点和结点指针类型
***********/
Status ClearList_L(LinkList &L)
/* 将带头结点单链表L置为空表,并返回OK。*/
/* 若L不是带头结点单链表,则返回ERROR。 */
{
if(L == NULL)
return ERROR;
LNode *t;
LNode *p = L->next;
while(p!=NULL){
t = p;
p = p->next;
free(t);
}
L->next = NULL;
return OK;
}
PE77
/**********
【题目】试写一算法,实现带头结点单链表的求表长度操作。
单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList; // 结点和结点指针类型
***********/
int ListLength_L(LinkList L)
/* 求带头结点单链表L的长度,并返回长度值。*/
/* 若L不是带头结点单链表,则返回-1。 */
{
if(L == NULL)
return -1;
int count = 0;
LNode *p = L;
while(p->next != NULL){
p = p->next;
count ++;
}
return count;
}
PE82
/**********
【题目】试写一算法,在带头结点单链表的第i元素起的
所有元素从链表移除,并构成一个带头结点的新链表。
带头结点单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status Split_L(LinkList L, LinkList &Li, int i)
/* 在带头结点单链表L的第i元素起的所有元素 */
/* 移除,并构成带头结点链表Li,返回OK。 */
/* 若参数不合理,则Li为NULL,返回ERROR。 */
{
if(L->next == NULL || i <= 0){
Li = NULL;
return ERROR;
}
LNode *p = L;
while(i>1 && p->next != NULL){
p = p->next;
i--;
}
if(i>1 || p->next == NULL){
Li = NULL;
return ERROR;
}
Li = (LNode*)malloc(sizeof(LNode));
Li->next = p->next;
p->next = NULL;
return OK;
}
PE84
/**********
【题目】试写一算法,在带头结点单链表删除第i元素到e。
带头结点单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status Delete_L(LinkList L, int i, ElemType &e)
/* 在带头结点单链表L删除第i元素到e,并返回OK。*/
/* 若参数不合理,则返回ERROR。 */
{
if(NULL == L || i <= 0)
return ERROR;
LNode *p = L;
LNode *t;
while(p!=NULL && i>0){
t = p;
p = p->next;
i--;
}
if(p==NULL)
return ERROR;
else {
t->next = p->next;
e = p->data;
free(p);
return OK;
}
}
PE86
/**********
【题目】试写一算法,在带头结点单链表的第i元素起的
所有元素从链表移除,并构成一个带头结点的新链表。
带头结点单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status Split_L(LinkList L, LinkList &Li, int i)
/* 在带头结点单链表L的第i元素起的所有元素 */
/* 移除,并构成带头结点链表Li,返回OK。 */
/* 若参数不合理,则Li为NULL,返回ERROR。 */
{
if(L->next == NULL || i <= 0){
Li = NULL;
return ERROR;
}
LNode *p = L;
while(i>1 && p->next != NULL){
p = p->next;
i--;
}
if(i>1 || p->next == NULL){
Li = NULL;
return ERROR;
}
Li = (LNode*)malloc(sizeof(LNode));
Li->next = p->next;
p->next = NULL;
return OK;
}
PE88
/**********
【题目】试写一算法,在带头结点单链表删除第i元素
起的所有元素。
带头结点单链表的类型定义为:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status Cut_L(LinkList L, int i)
/* 在带头结点单链表L删除第i元素起的所有元素,并返回OK。*/
/* 若参数不合理,则返回ERROR。 */
{
if(L == NULL || i<= 0)
return ERROR;
LNode *p = L;
LNode *t = p;
while(p!=NULL && i > 0){
t = p;
p = p->next;
i--;
}
if(p==NULL&& i>=0)
return ERROR;
else{
t ->next = NULL;
while(p!=NULL){
t = p;
p = p->next;
free(t);
}
}
return OK;
}
PE90
/**********
/**********
【题目】试写一算法,删除带头结点单链表中所有值
为x的元素,并释放被删结点空间。
单链表类型定义如下:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status DeleteX_L(LinkList L, ElemType x)
/* 删除带头结点单链表L中所有值为x的元素, */
/* 并释放被删结点空间,返回实际删除的元素个数。*/
{
int count = 0;
if(L == NULL)
return count;
LNode *p,*t;
t = L;
p = L->next;
while(p!=NULL){
if(p->data == x){
count ++;
t->next = p->next;
free(p);
p = t;
}
t = p;
p = p->next;
}
return count;
}
PE91
/**********
【题目】试写一算法,删除带头结点单链表中所有值
小于x的元素,并释放被删结点空间。
单链表类型定义如下:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
**********/
Status DeleteSome_L(LinkList L, ElemType x)
/* 删除带头结点单链表L中所有值小于x的元素, */
/* 并释放被删结点空间,返回实际删除的元素个数。*/
{
int count = 0;
if(L == NULL)
return count;
LNode *p,*t;
t = L;
p = L->next;
while(p!=NULL){
if(p->data < x){
count ++;
t->next = p->next;
free(p);
p = t;
}
t = p;
p = p->next;
}
return count;
}
DC03
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] = L.rcd[i+1];
j = i+1;
while(L.rcd[j-1].key > L.rcd[L.length+1].key && j>=2){
L.rcd[j] = L.rcd[j-1];
j--;
}
L.rcd[j] = L.rcd[L.length+1];
}
}
}
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;
int change = L.length;
for (i = L.length ; i > 1&&change; --i){
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 */
{
RcdType a[MAXSIZE + 1];
int c[MAXSIZE + 1] = {0};
int n = L.length;
int i,j;
for (i = 1;i<=n; i++){
for (j = 1;j<=n; j++)
if (L.rcd[i].key > L.rcd[j].key)
c[i]++;
}
for (i = 1;i <= n; i++){
a[i] = L.rcd[i];
}
for (i = 1;i <= n; i++){
L.rcd[c[i]+1] = a[i];
}
}
DC04
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输出关键字 */
{
if(ht.rcd == NULL || ht.size <= 0 || ht.count <0)
return;
int i,j;
for(i = 'A';i<='Z';i++){
for(j = 0;j<ht.size;j++){
if((int)ht.rcd[j].key[0] == i&&ht.rcd[j].tag == 1){
print(ht.rcd[j].key);
}
}
}
}
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); */
{
H.rcd = (HLink*)malloc(H.size*sizeof(HLink));
if(H.rcd == NULL )
return UNSUCCESS;
for(int i = 0;i<H.size;i++)
H.rcd[i] = NULL;
HLink p,t;
for(int j =0;j<n;j++){
t = (HLink)malloc(sizeof(struct HNode));
if(t == NULL)
return UNSUCCESS;
else H.count++;
if(H.rcd[Hash(H,es[j])]==NULL){
printf("%d\n",Hash(H,es[j]));
t->data = es[j];
H.rcd[Hash(H,es[j])] = t;
t->next = NULL;
}else{
p = H.rcd[Hash(H,es[j])];
while(p!=NULL){
if(p->data == es[j])
break;
else p = p->next;
}
if(p == NULL){
p = H.rcd[Hash(H,es[j])];
t->data = es[j];
t->next = p;
H.rcd[Hash(H,es[j])]= t;
}
}
}
return SUCCESS;
}
DC05
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)
return -1;
else if(m ==0 && n>=0)
return 0;
else if(m>0 && n>=0)
return G(m-1,2*n)+n;
}
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)
return -1;
else if(!n)
return n+1;
else return n*F(n/2);
}
PE06
/**********
【题目】求解平方根 的迭代函数定义如下:
sqrt(A,p,e) = p 当|p*p-A|<e
sqrt(A,p,e) = sqrt(A,(p+A/p)/2,e) 当|p*p-A|>=e
其中,p是A的近似平方根,e是结果允许误差。试写出相
应的递归算法。
**********/
float Sqrt(float A, float p, float e)
{
if((p*p-A)<e&&(A-p*p)<e){
return p;
}else{
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;
else if(!m)
return n+1;
else{
if(!n)
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 */
{
if(!n)
return 1;
else if(n<0)
return -1;
if(n<=1)
return 1;
int *t;
t = (int *)malloc(sizeof(int)*(n+1)) ;
t[0] = 1;
t[1] = 1;
int pos = 0;
int cnt = 2;
for(int i = 2;i<=n;i++){
if(i%2 == 0)
pos++;
t[i] = i*t[pos];
}
return t[n];
}
PE16
/**********
【题目】求解平方根 的迭代函数定义如下:
sqrt(A,p,e) = p 当|p*p-A|<e
sqrt(A,p,e) = sqrt(A,(p+A/p)/2,e) 当|p*p-A|>=e
其中,p是A的近似平方根,e是结果允许误差。试写出相
应的非递归算法。
**********/
float Sqrt(float A, float p, float e)
{
while(true){
p = (p+A/p)/2;
if(p*p-A<e && A-p*p<e)
break;
}
return p;
}
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 t = g[i0][j0];
g[i0][j0] = c;
int x[4]={1,-1,0,0};
int y[4]={0,0,1,-1};
int i;
for(i=0;i<4;i++){
if(i0+x[i]>m||i0+x[i]<1||j0+y[i]>n||j0+y[i]<1)
continue;
if(g[i0+x[i]][j0+y[i]] == t){
ChangeColor(g,m,n,c,i0+x[i],j0+y[i]);
}
}
}
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 max,dep;
GList pp;
if(NULL == ls)
return 1;
if(ls->tag == ATOM)
return 0;
for(max = 0, pp = ls ; pp ; pp = pp->un.ptr.tp){
dep = GListDepth(pp->un.ptr.hp)+1;
if(dep > max)
max = dep;
}
return max;
}
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){
if(A->tag == B->tag){
if(A->tag == ATOM && A->un.atom == B->un.atom)
return TRUE;
if(A->tag == LIST && Equal(A->un.ptr.hp,B->un.ptr.hp) && Equal(A->un.ptr.tp,B->un.ptr.tp))
return TRUE;
return FALSE;
}else return FALSE;
}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 == NULL)
return;
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);
}
}
DC06
PE06
/**********
【题目】若两棵二叉树T1和T2皆为空,或者皆不空
且T1的左、右子树和T2的左、右子树分别相似,则
称二叉树T1和T2相似。试编写算法,判别给定两棵
二叉树是否相似。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
Status Similar(BiTree T1, BiTree T2)
/* 判断两棵二叉树是否相似的递归算法 */
{
if(T1 == NULL && T2 == NULL )
return TRUE;
else if(T1!= NULL && T2!=NULL){
return Similar(T1->lchild,T2->lchild)&&Similar(T1->rchild,T2->rchild);
}else return FALSE;
}
PE11
/**********
【题目】编写递归算法,求对二叉树T先序遍历时
第k个访问的结点的值。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
int countNode(BiTree T){
int count = 1;
if(T->lchild != NULL)
count += countNode(T->lchild);
if(T->rchild != NULL)
count += countNode(T->rchild);
return count;
}
TElemType PreOrderK(BiTree T, int k)
/* 求对二叉树T先序遍历时第k个访问的结点的值。*/
/* 若失败,则返回'#' */
{
if(T == NULL)
return '#';
if(k == 1)
return T->data;
int t = 0;
TElemType x = '#';
if(T->lchild != NULL){
x = PreOrderK(T->lchild,k-1);
t = countNode(T->lchild);
}
if(T->rchild != NULL && x== '#'){
x = PreOrderK(T->rchild,k-1-t);
}
return x;
}
PE12
/**********
【题目】编写递归算法,计算二叉树T中叶子结点的数目。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
int Leaves(BiTree T)
/* 计算二叉树T中叶子结点的数目 */
{
if(T == NULL)
return 0;
int count = 0;
if(T->lchild == NULL && T->rchild == NULL)
return 1;
if(T->lchild != NULL)
count += Leaves(T->lchild);
if(T->rchild != NULL)
count += Leaves(T->rchild);
return count;
}
PE21
/**********
【题目】试利用栈及其基本操作写出二叉树T的非递归
的先序遍历算法。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef BiTree SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
**********/
void goLeft(BiTree T,Stack &s,void (*visit)(TElemType)){
while(T!= NULL){
Push(s,T);
visit(T->data);
T = T->lchild;
}
}
void PreOrder(BiTree T, void (*visit)(TElemType))
/* 使用栈,非递归先序遍历二叉树T, */
/* 对每个结点的元素域data调用函数visit */
{ if(T == NULL)
return;
Stack s;
InitStack(s);
SElemType p = T;
goLeft(T,s,visit);
while(!StackEmpty(s)){
SElemType t;
Pop(s,t);
if(t->rchild != NULL)
goLeft(t->rchild,s,visit);
}
}
PE23
/**********
【题目】试利用栈及其基本操作写出二叉树T的非递归
的后序遍历算法(提示:为分辨后序遍历时两次进栈的
不同返回点,需在指针进栈时同时将一个标志进栈)。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef struct {
struct BiTNode *ptr; // 二叉树结点的指针类型
int tag; // 0..1
} SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
**********/
void PostOrder(BiTree T, void (*visit)(TElemType))
/* 使用栈,非递归后序遍历二叉树T, */
/* 对每个结点的元素域data调用函数visit */
{
SElemType p,t;
Stack s;
InitStack(s);
p.ptr = T;
while(p.ptr){
if(p.ptr->lchild && p.ptr->rchild){//both
p.tag = 1;
Push(s,p);
p.ptr = p.ptr->lchild;
}
else if(p.ptr->lchild && !p.ptr->rchild){//only left
p.tag = 0;
Push(s,p);
p.ptr = p.ptr->lchild;
}
else if(!p.ptr->lchild && p.ptr->rchild){//only right
p.tag = 0;
Push(s,p);
p.ptr = p.ptr->rchild;
}
else if(!p.ptr->lchild && !p.ptr->rchild){//leaves
visit(p.ptr->data);
Pop(s,t);
if(t.tag == 1){
t.tag = 0;
Push(s,t);
p.ptr = t.ptr->rchild;
}else if(t.tag == 0){
visit(t.ptr->data);
while(!StackEmpty(s)){
Pop(s,t);
if(t.tag == 0)
visit(t.ptr->data);
else{
t.tag = 0;
Push(s,t);
p.ptr = t.ptr->rchild;
break;
}
}
if(StackEmpty(s)){
p.ptr = NULL;
}
}
}
}
}
PE27
/**********
【题目】二叉树采用三叉链表的存储结构,试编写
不借助栈的非递归中序遍历算法。
三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *parent, *lchild, *rchild;
} TriTNode, *TriTree;
**********/
void InOrder(TriTree PT, void (*visit)(TElemType))
/* 不使用栈,非递归中序遍历二叉树PT, */
/* 对每个结点的元素域data调用函数visit */
{
TriTNode *p,*t;
p = PT;
while(p){
if(p->lchild)
p = p->lchild;
else{
visit(p->data);
if(p->rchild)
p = p->rchild;
else{
t = p;
p = p->parent;
while(p && (p->lchild != t ||!p->rchild)){
if (p->lchild == t)
visit(p->data);
t = p;
p = p->parent;
}
if(p){
visit(p->data);
p = p->rchild;
}
}
}
}
}
PE29
/**********
【题目】假设在三叉链表的结点中增设一个标志域
(mark取值0,1或2)以区分在遍历过程中到达该结点
时应继续向左或向右或访问该结点。试以此存储结
构编写不用栈辅助的二叉树非递归后序遍历算法。
带标志域的三叉链表类型定义:
typedef struct TriTNode {
TElemType data;
struct TriTNode *lchild, *rchild, *parent;
int mark; // 标志域
} TriTNode, *TriTree;
**********/
void PostOrder(TriTree T, void (*visit)(TElemType))
/* 不使用栈,非递归后序遍历二叉树T, */
/* 对每个结点的元素域data调用函数visit */
{
TriTree p;
p = T;
while(p){
if(p->mark == 0){
p->mark = 1;
if(p->lchild)
p = p->lchild;
}
else if(p->mark == 1){
p->mark = 2;
if(p->rchild)
p = p->rchild;
}
else if(p->mark == 2){
visit(p->data);
p = p->parent;
}
}
}
PE33
/**********
【题目】编写递归算法,将二叉树中所有结点的
左、右子树相互交换。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
void ExchangeSubTree(BiTree &T)
/* 将二叉树中所有结点的左、右子树相互交换 */
{
if(T == NULL)
return;
else{
BiTNode *t;
t = T->lchild;
T->lchild = T->rchild;
T->rchild = t;
ExchangeSubTree(T->lchild);
ExchangeSubTree(T->rchild);
}
}
PE37
/**********
【题目】编写递归算法:求二叉树中以元素值
为x的结点为根的子树的深度。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
int Depthx(BiTree T, TElemType x)
/* 求二叉树中以值为x的结点为根的子树深度 */
{ if(T == NULL)
return 0;
int ldepth = 0;
int rdepth = 0;
if(T->data == x){
if(T->lchild != NULL)
ldepth = Depthx(T->lchild,T->lchild->data)+1;
if(T->rchild != NULL)
rdepth = Depthx(T->rchild,T->rchild->data)+1;
if(T->lchild == NULL && T->rchild == NULL)
return 1;
}else{
if(T->lchild != NULL)
ldepth = Depthx(T->lchild,x);
if(T->rchild != NULL)
rdepth = Depthx(T->rchild,x);
}
return ldepth>rdepth?ldepth:rdepth;
}
PE40
/**********
【题目】编写递归算法:对于二叉树中每一个元素值为x
的结点,删去以它为根的子树,并释放相应的空间。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
void ReleaseX(BiTree &T, char x)
/* 对于二叉树T中每一个元素值为x的结点, */
/* 删去以它为根的子树,并释放相应的空间 */
{
if(T == NULL)
return;
if(T->data == x){
if(T->lchild != NULL)
ReleaseX(T->lchild,T->lchild->data);
if(T->rchild != NULL)
ReleaseX(T->rchild,T->rchild->data);
free(T);
return;
}else{
if(T->lchild != NULL){
ReleaseX(T->lchild,x);
if(T->lchild->data == x)
T->lchild = NULL;
}
if(T->rchild != NULL){
ReleaseX(T->rchild,x);
if(T->rchild->data == x)
T->rchild = NULL;
}
}
}
PE43
/**********
【题目】编写复制一棵二叉树的递归算法。
二叉链表类型定义:
typedef char TElemType; // 设二叉树的元素为char类型
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
**********/
void CopyBiTree(BiTree T, BiTree &TT)
/* 递归复制二叉树T得到TT */
{
if(T == NULL){
TT = NULL;
return;
}
BiTree p,lchild,rchild;
if(TT == NULL){
p = (BiTree)malloc(sizeof(BiTNode));
p->data = T->data;
TT = p;
}
if(T->lchild != NULL){
lchild = (BiTree)malloc(sizeof(BiTNode));
lchild->data = T->lchild->data;
TT->lchild = lchild;
CopyBiTree(T->lchild,lchild);
}
if(T->rchild != NULL){
rchild = (BiTree)malloc(sizeof(BiTNode));
rchild->data = T->rchild->data;
TT->rchild = rchild;
CopyBiTree(T->rchild,rchild);
}
}
PE47
/**********
【题目】编写算法判别给定二叉树是否为完全二叉树。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
可用队列类型Queue的相关定义:
typedef BiTree QElemType; // 设队列元素为二叉树的指针类型
Status InitQueue(Queue &Q);
Status EnQueue(Queue &Q, QElemType e);
Status DeQueue(Queue &Q, QElemType &e);
Status GetHead(Queue Q, QElemType &e);
Status QueueEmpty(Queue Q);
**********/
Status CompleteBiTree(BiTree T)
/* 判别二叉树T是否为完全二叉树 */
{
if(NULL == T)
return TRUE;
Queue q;
InitQueue(q);
EnQueue(q,T);
BiTree p;
while(!QueueEmpty(q)){
GetHead(q,p);
DeQueue(q,p);
if(!p->lchild && p->rchild)
return FALSE;
else if(p->lchild && p->rchild){
EnQueue(q,p->lchild);
EnQueue(q,p->rchild);
}
else if(p->lchild && !p->rchild){
EnQueue(q,p->lchild);
while(!QueueEmpty(q)){
GetHead(q,p);
DeQueue(q,p);
if(p->lchild || p->rchild)
return FALSE;
}
}else if(!p->lchild && !p->rchild){
while(!QueueEmpty(q)){
GetHead(q,p);
DeQueue(q,p);
if(p->lchild || p->rchild)
return FALSE;
}
}
}
return TRUE;
}
PE50
/**********
【题目】试编写一个二叉排序树的判定算法。
二叉排序树的类型BSTree定义如下:
typedef struct {
KeyType key;
... ... // 其他数据域
} TElemType;
typedef struct BiTNode {
TElemType data;
struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;
**********/
Status IsBSTree(BSTree T)
/* 判别二叉树T是否为二叉排序树。*/
/* 若是,则返回TRUE,否则FALSE */
{
if(T==NULL||(T->lchild==NULL&&T->rchild==NULL))
return TRUE;
KeyType i = T->data.key;
if(T->lchild && T->lchild->data.key >= i )
return ERROR;
if(T->rchild && T->rchild->data.key <= i )
return ERROR;
if(IsBSTree(T->lchild) && IsBSTree(T->rchild))
return TRUE;
}
PE53
/**********
【题目】编写递归算法,从大到小输出给定二叉排序树
中所有关键字不小于x的数据元素。
二叉排序树的类型BSTree定义如下:
typedef struct {
KeyType key;
... ... // 其他数据域
} TElemType;
typedef struct BSTNode {
TElemType data;
struct BSTNode *lchild,*rchild;
}BSTNode, *BSTree;
**********/
void OrderOut(BSTree T, KeyType k, void(*visit)(TElemType))
/* 调用visit(T->data)输出 */
{
if(T == NULL)
return;
OrderOut(T->rchild,k,visit);
if(T->data.key >= k)
visit(T->data);
OrderOut(T->lchild,k,visit);
}
PE60
/**********
【题目】试写一非递归算法,在二叉查找树T中插入元素e。
二叉查找树的类型BSTree定义如下:
typedef struct {
KeyType key;
... ... // 其他数据域
} TElemType;
typedef struct BSTNode {
TElemType data;
struct BSTNode *lchild,*rchild;
} BSTNode, *BSTree;
**********/
Status InsertBST_I(BSTree &T, TElemType k)
/* 在二叉查找树T中插入元素e的非递归算法 */
{
BSTree p = T;
BSTree new;
new = (BSTree)malloc(sizeof(BSTNode));
if(!new)
return OVERFLOW;
new->lchild = NULL;
new->rchild = NULL;
new->data = k;
while(p){
if(p->data.key > k.key){
if(p->lchild != NULL)
p = p->lchild;
else p->lchild = new;
}
else if(p->data.key < k.key){
if(p->rchild != NULL)
p = p->rchild;
else p->rchild = new;
}else if(p->data.key == k.key)
return FALSE;
}
return OK;
}
PE68
/**********
【题目】试编写算法,求二叉树T中结点a和b的最近共同祖先。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;
可用栈类型Stack的相关定义:
typedef struct {
BiTNode *ptr; // 二叉树结点的指针类型
int tag; // 0..1
} SElemType; // 栈的元素类型
Status InitStack(Stack &S);
Status StackEmpty(Stack S);
int StackLength(SqStack S);
Status Push(Stack &S, SElemType e);
Status Pop(Stack &S, SElemType &e);
Status GetTop(Stack S, SElemType &e);
**********/
void findElem(BiTree T,TElemType e,Stack &s)
{
SElemType se;
se.ptr=T; se.tag=0;
int i=0;
while(true) {
while(se.ptr!=NULL) {
if(se.ptr->data==e)
return;
Push(s,se);
se.ptr=se.ptr->lchild;
}
while(!StackEmpty(s)) {
Pop(s,se);
if(se.ptr->data==e)
return ;
if(se.ptr->rchild) {
if(se.tag==0) {
se.tag=1;
Push(s,se);
se.tag=0;
se.ptr=se.ptr->rchild;
break;
}
}
}
if(StackEmpty(s))
return;
}
}
BiTree CommAncestor(BiTree T, TElemType a, TElemType b)
/* 求二叉树T中结点a和b的最近共同祖先 */
{
Stack sa,sb,s;
SElemType ea,eb;
BiTree ta,tb;
InitStack(sa);
InitStack(sb);
InitStack(s);
findElem(T,a,sa);
findElem(T,b,sb);
while(!StackEmpty(sa)){
Pop(sa,ea);
ta=ea.ptr;
s=sb;
while(!StackEmpty(s)){
Pop(s,eb);
tb=eb.ptr;
if(ta->data==tb->data)
return ta;
}
}
}
PE75
/**********
【题目】在二叉排序树的每个结点中增设一个lsize域,
其值为该结点的左子树中的结点数加1。试编写时间复杂
度为O(logn)的算法,求树中第k小的结点的位置。
二叉排序树的类型BSTree定义如下:
typedef char KeyType;
typedef struct BSTNode {
KeyType key;
struct BSTNode *lchild,*rchild;
int lsize; // 新增域,值为左子树的结点数+1
} BSTNode, *BSTree;
**********/
BSTNode *Ranking(BSTree T, int k)
/* 在含lsize域的二叉排序树T中,*/
/* 求指向T中第k小的结点的指针 */
{
if(T==NULL||k<=0)return NULL;
if(T->lsize==k)return T;
if(T->lsize>k)return Ranking(T->lchild,k);
if(T->lsize<k)return Ranking(T->rchild,k-T->lsize);
}
PE77
/**********
【题目】假设二叉排序树T的每个结点的平衡因子域bf当前
均为0。试编写算法,求二叉排序树T的深度,并为每个结点
的bf域赋予正确的平衡因子值。
平衡二叉排序树的类型BBSTree定义如下:
typedef char KeyType;
typedef struct BBSTNode {
KeyType key;
int bf; // 平衡因子
struct BBSTNode *lchild,*rchild;
} BBSTNode, *BBSTree;
**********/
int Depth_BF(BBSTree T)
/* 求二叉排序树T的深度,并为每个结点 */
/* 的bf域赋予正确的平衡因子值。 */
{
if(T==NULL)
return 0;
int i=1,a,b;
if(T->rchild==NULL&&T->lchild==NULL){
T->bf=0;
return i;
}
a=1+Depth_BF(T->lchild);
b=1+Depth_BF(T->rchild);
T->bf=a-b;
return a>b?a:b;
}
PE82
/**********
【题目】编写平衡二叉排序树的右平衡处理算法。
平衡二叉排序树的类型BBSTree定义如下:
typedef char KeyType;
typedef struct BBSTNode {
KeyType key;
int bf; // 平衡因子
struct BBSTNode *lchild,*rchild;
} BBSTNode, *BBSTree;
可调用下列旋转调整操作:
void L_Rotate(BBSTree &p); // 对最小失衡子树p做左旋调整
void R_Rotate(BBSTree &p); // 对最小失衡子树p做右旋调整
**********/
void RightBalance(BBSTree &T)
/* 实现对二叉树T的右平衡处理 */
{
BBSTNode *rc = T->rchild;
BBSTNode *rlchild;
switch(rc->bf) {
case 1:
rlchild = rc->lchild;
switch(rlchild->bf) {
case 1:
T->bf = 0;
rc->bf = -1;
break;
case 0:
T->bf = 0;
rc->bf = 0;
break;
case -1:
T->bf = 1;
rc->bf = 0;
break;
}
rlchild->bf = 0;
R_Rotate(T->rchild);
L_Rotate(T);
break;
case -1:
T->bf = 0;
rc->bf = 0;
L_Rotate(T);
break;
}
}
DC07
PE15
/**********
【题目】试编写算法,对一棵以孩子兄弟链表表示
的树统计叶子的个数。
孩子兄弟链表类型定义:
typedef struct CSTNode {
TElemType data;
struct CSTNode *firstChild, *nextSibling;
} CSTNode, *CSTree;
**********/
int Leave(CSTree T) /* 统计树T的叶子数 */
{
if(!T)
return 0;
if(!T->firstChild)
return 1; //叶子结点
else
{
int count=0;
for(CSTree p=T->firstChild;p;p=p->nextSibling)
count+=Leave(p);
return count; //各子树的叶子数之和
}
}
PE22
/**********
【题目】试编写算法,对以双亲表示法存储的树计算深度。
typedef struct {
TElemType data;
int parent; // 双亲位置
} PTNode; // 结点类型
typedef struct {
PTNode nodes[MAX_TREE_SIZE]; // 结点存储空间
int n, r; // 结点数和根的位置
} PTree;
**********/
int PTreeDepth(PTree T) /* 求树T的深度 */
{
int max=0,depth,p;
for(int i=0;i<T.n;i++)
{
depth = 1;
p=T.nodes[i].parent;
while(p!=-1)
{
p = T.nodes[p].parent;
depth++;
}
if(max<depth) max = depth;
}
return max;
}
PE17
/**********
【题目】试编写算法,求一棵以孩子兄弟链表表示的树的度。
孩子兄弟链表类型定义:
typedef struct CSTNode {
TElemType data;
struct CSTNode *firstChild, *nextSibling;
} CSTNode, *CSTree;
**********/
int Degree(CSTree T) /* 求树T的度 */
{
int max,curdeg,deg;
CSTree p;
if(!T) return 0;
else {
max=0;curdeg=0;
for( p = T->firstChild; p!=NULL; p= p->nextSibling){
curdeg++;
deg = Degree(p);
if(deg>max)
max = deg;
}
return max>curdeg?max:curdeg;
}
}
PE24
/**********
【题目】试编写算法,对以双亲孩子表示法存储的树计算深度。
孩子链表类型定义:
typedef struct ChildNode { // 孩子结点
int childIndex;
struct ChildNode *nextChild;
} ChildNode; // 孩子结点类型
typedef struct {
TElemType data;
int parent; // 双亲位置
struct ChildNode *firstChild; // 孩子链表头指针
} PCTreeNode; // 结点类型
typedef struct {
PCTreeNode *nodes; // 结点存储空间
int n, r; // 结点数和根的位置
} PCTree;
**********/
int PTreeDepth(PCTree T)
{
int count = 1,i,max = 0;
if(T.n==1) return 1;
for(i=0;i<T.n;i++)
if(T.nodes[i].parent>max)
max = T.nodes[i].parent;
for(i=max; i!=-1; i=T.nodes[i].parent)
count++;
return count;
}
int PCTreeDepth(PCTree T) /* 求树T的深度 */
{
int i=0,max=1;
ChildNode *p;
if(NULL==T.nodes)
return 0;
T.nodes[i].parent=-1;
for(i=0;i<T.n;i++)
if(T.nodes[i].firstChild!=NULL){
p=T.nodes[i].firstChild;
while(p)
{
T.nodes[p->childIndex].parent = i;
p = p->nextChild;
}
}
return PTreeDepth(T);
}
PE26
/**********
【题目】试编写算法,对以孩子-兄弟链表表示的树计算深度。
孩子兄弟链表类型定义:
typedef struct CSTNode {
TElemType data;
struct CSTNode *firstChild, *nextSibling;
} CSTNode, *CSTree;
**********/
int TreeDepth(CSTree T)
/* 求树T的深度 */
{
int max,depth;
if(!T) return 0;
else {
for(max=0,T=T->firstChild;T;T=T->nextSibling)
if((depth=TreeDepth(T))>max)
max=depth;
return max+1;
}
}
PE35
/**********
【题目】已知一棵树的由根至叶子结点按层次输出的
结点序列及每个结点的度。试编写算法,构造此树的
孩子兄弟链表。
孩子兄弟链表类型定义:
typedef struct CSTNode {
TElemType data;
struct CSTNode *firstChild, *nextSibling;
} CSTNode, *CSTree;
**********/
CSTree find(CSTree T,char x)
{
if(x==T->data)return T;
if(T==null)return null;
CSTree m,n;
m=find(T->firstChild,x);
if(m==null){
n=find(T->nextSibling,x);
return n;
}
else return m;
}
void BuildCSTree(CSTree &T, char *node, int *degree)
/* 由结点的层序序列node和各结点的度degree构造树的孩子兄弟链表T */
{
int childnum,i,j;
CSTNode *p,*cur;
char nextfather;
T=(CSTree)malloc(sizeof(CSTNode));
T->data=node[i++];
cur=T;
while(node[i]){
childnum=degree[j];
cur=find(T,node[j]);
while(childnum!=0){
if(childnum==degree[j]){
p=(CSTree)malloc(sizeof(CSTNode));
p->data=node[i++];
cur->firstChild=p;
cur=cur->firstChild;
}
else{
p=(CSTree)malloc(sizeof(CSTNode));
p->data=node[i++];
cur->nextSibling=p;
cur=cur->nextSibling;
}
childnum--;
}
j++;
}
}
PE63
/**********
【题目】试编写非递归算法,实现并查集带路径压缩的
查找操作。
并查集的类型定义如下:
typedef struct {
int *parent;
int n;
} MFSet;
**********/
int find(MFSet S, int i)
/* 并查集带路径压缩的查找的非递归实现 */
{
if(i<0||i>=S.n)
return -1;
int parent,p,root;
root=i;
parent=S.parent[i];
while(parent!=-1)
{
root=parent;
parent=S.parent[parent];
}
p=i;
parent=S.parent[i];
while(parent!=-1)
{
S.parent[p]=root;
p=parent;
parent=S.parent[parent];
}
return p;
}
DC08
PE12
/**********
【题目】编写算法,创建有向图的邻接数组存储结构。
图的邻接数组存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define MAX_VEX_NUM 4
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef int VRType;
typedef char InfoType;
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct {
VRType adj; // 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;
// 对带权图,则为权值类型
InfoType *info; // 该弧相关信息的指针(可无)
}ArcCell;//,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
ArcCell arcs[MAX_VEX_NUM][MAX_VEX_NUM]; // 关系数组
VexType vexs[MAX_VEX_NUM]; // 顶点数组
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
} MGraph; // 邻接数组类型
typedef struct {
VexType v, w;
int inf;
} ArcInfo;
可调用以下基本操作:
Status InitGraph(MGraph &G, GraphKind kind, int n);
// 初始化含n个顶点空间的kind类的空图G
int LocateVex(MGraph G, VexType v); // 查找顶点v在图G中的位序
**********/
Status CreateDG(MGraph &G, VexType *vexs, int n,
ArcInfo *arcs, int e)
/* 创建含n个顶点和e条边的有向图G,vexs为顶点信息,arcs为边信息 */
{
if(ERROR == InitGraph(G, DG, n))
return ERROR;
int cnt,i,j;
for(cnt = 0;cnt < n;cnt++ ){
G.vexs[cnt] = vexs[cnt];
}
for(cnt = 0;cnt<e;cnt++){
//i = LocateVex(G,arcs[cnt].v); what the hell?
//j = LocateVex(G,arcs[cnt].w); why the function locatevex always -1???
for(i = 0;i<n;i++)
if(G.vexs[i] == arcs[cnt].v)
break;
for(j = 0;j<n;j++)
if(G.vexs[j] == arcs[cnt].w)
break;
if(i == n || j == n)
return ERROR;
G.arcs[i][j].adj = 1;
}
G.n = n;
G.e = e;
}
PE15
/**********
【题目】编写算法,在图G中,相对于k顶点的当前
邻接顶点m顶点,求下一个邻接顶点。
图的邻接数组存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define MAX_VEX_NUM 4
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef int VRType;
typedef char InfoType;
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct {
VRType adj; // 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;
// 对带权图,则为权值类型
InfoType *info; // 该弧相关信息的指针(可无)
}ArcCell;//,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
ArcCell arcs[MAX_VEX_NUM][MAX_VEX_NUM]; // 关系数组
VexType vexs[MAX_VEX_NUM]; // 顶点数组
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
} MGraph; // 邻接数组类型
**********/
int NextAdjVex(MGraph G, int k, int m)
/* 在图G中,相对于k顶点的当前邻接顶点m顶点,求下一个邻接顶点 */
{
//the graph is null,why the point is zero???
if(G.n == 0 && G.e == 0)
return 0;
//find the next possible point
int i = m+1;
for(;i<G.n;i++)
if(G.arcs[k][i].adj != 0 && G.arcs[k][i].adj != INFINITY)
return i;
return -1;
}
PE17
/**********
【题目】编写算法,在图G中置顶点v到顶点w的弧或边。
图的邻接数组存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define MAX_VEX_NUM 4
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef int VRType;
typedef char InfoType;
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct {
VRType adj; // 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否;
// 对带权图,则为权值类型
InfoType *info; // 该弧相关信息的指针(可无)
}ArcCell;//,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
ArcCell arcs[MAX_VEX_NUM][MAX_VEX_NUM]; // 关系数组
VexType vexs[MAX_VEX_NUM]; // 顶点数组
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
} MGraph; // 邻接数组类型
可调用以下基本操作:
int LocateVex(MGraph G, VexType v); // 查找顶点v在图G中的位序
**********/
Status SetArc(MGraph &G, VexType v, VexType w, ArcCell info)
/* 在图G中置顶点v到顶点w的弧或边 */
{
if(G.n == 0 || v == w)
return ERROR;
int i,j;
i = LocateVex(G,v);
j = LocateVex(G,w);
if(i==-1||j==-1 || i>=G.n || j>=G.n)
return ERROR;
if((UDG == G.kind || DG == G.kind)&&info.adj!=1)
return ERROR;
if(G.arcs[i][j].adj >0 && G.arcs[i][j].adj != INFINITY)
return OK;
G.arcs[i][j].adj = info.adj;
if(UDG == G.kind || UDN == G.kind)
G.arcs[j][i].adj = info.adj;
G.e ++;
return OK;
}
PE21
/**********
【题目】编写算法,计算以邻接表方式存储的有向图G中k顶点的出度。
图的邻接表存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct AdjVexNode {
int adjvex; // 邻接顶点在顶点数组中的位序
struct AdjVexNode *next; // 指向下一个邻接顶点(下一条边或弧)
int info; // 存储边(弧)相关信息,对于非带权图可不用
} AdjVexNode, *AdjVexNodeP; // 邻接链表的结点类型
typedef struct VexNode {
VexType data; // 顶点值,VexType是顶点类型,由用户定义
struct AdjVexNode *firstArc; // 邻接链表的头指针
} VexNode; // 顶点数组的元素类型
typedef struct {
VexNode *vexs; // 顶点数组,用于存储顶点信息
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
int *tags; // 标志数组
} ALGraph; // 邻接表类型
**********/
int outDegree(ALGraph G, int k)
/* 求有向图G中k顶点的出度。若k顶点不存在,则返回-1 */
{
if(k<0 || k>= G.n)
return -1;
AdjVexNode *p = G.vexs[k].firstArc;
int cnt = 0;
while(p!=NULL){
cnt++;
p = p->next;
}
return cnt;
}
PE22
/**********
【题目】编写算法,计算以邻接表方式存储的有向图G中
k顶点的入度。
图的邻接表存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct AdjVexNode {
int adjvex; // 邻接顶点在顶点数组中的位序
struct AdjVexNode *next; // 指向下一个邻接顶点(下一条边或弧)
int info; // 存储边(弧)相关信息,对于非带权图可不用
} AdjVexNode, *AdjVexNodeP; // 邻接链表的结点类型
typedef struct VexNode {
VexType data; // 顶点值,VexType是顶点类型,由用户定义
struct AdjVexNode *firstArc; // 邻接链表的头指针
} VexNode; // 顶点数组的元素类型
typedef struct {
VexNode *vexs; // 顶点数组,用于存储顶点信息
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
int *tags; // 标志数组
} ALGraph; // 邻接表类型
**********/
int inDegree(ALGraph G, int k)
/* 求有向图G中k顶点的入度。若k顶点不存在,则返回-1 */
{
if(k<0 || k>= G.n)
return -1;
int i,cnt;
cnt = 0;
for(i=0;i<G.n;i++){
AdjVexNode *p = G.vexs[i].firstArc;
while(p!=NULL){
if(p->adjvex == k)
cnt++;
p = p ->next;
}
}
return cnt;
}
PE32
/**********
【题目】编写算法,创建有向图的邻接表存储结构。
图的邻接表存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define MAX_VEX_NUM 4
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct AdjVexNode {
int adjvex; // 邻接顶点在顶点数组中的位序
struct AdjVexNode *next; // 指向下一个邻接顶点(下一条边或弧)
int info; // 存储边(弧)相关信息,对于非带权图可不用
} AdjVexNode, *AdjVexNodeP; // 邻接链表的结点类型
typedef struct VexNode {
VexType data; // 顶点值,VexType是顶点类型,由用户定义
struct AdjVexNode *firstArc; // 邻接链表的头指针
} VexNode; // 顶点数组的元素类型
typedef struct {
VexNode vexs[MAX_VEX_NUM]; // 顶点数组,用于存储顶点信息
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
int *tags; // 标志数组
} ALGraph; // 邻接表类型
可调用以下基本操作:
int LocateVex(ALGraph G, VexType v); // 查找顶点v在图G中的位序
**********/
Status CreateDG(ALGraph &G, VexType *vexs, int n,
ArcInfo *arcs, int e)
/* 创建含n个顶点和e条边的有向图G,vexs为顶点信息,arcs为边信息 */
{
if(n<0 || e <0)
return ERROR;
G.n = n;
G.e = e;
G.kind = DG;
int k,i,j;
G.tags = (int*)malloc(n*sizeof(int));
for(k=0;k<n;k++){
G.vexs[k].data = vexs[k];
G.tags[k] = UNVISITED;
G.vexs[k].firstArc = NULL;
}
for(k = 0;k<e;k++){
i = LocateVex(G,arcs[k].v);
j = LocateVex(G,arcs[k].w);
if(i == -1 || j == -1)
return ERROR;
AdjVexNode *p;
p =(AdjVexNode*)malloc(sizeof(AdjVexNode));
p->adjvex = j;
p->info = arcs[k].inf;
p->next = G.vexs[i].firstArc;
G.vexs[i].firstArc = p;
}
return OK;
}
PE34
/**********
【题目】编写算法,创建无向图的邻接表存储结构。
图的邻接表存储结构的类型定义如下:
#define UNVISITED 0
#define VISITED 1
#define MAX_VEX_NUM 4
#define INFINITY MAXINT // 计算机允许的整数最大值,即∞
typedef char VexType;
typedef enum {DG,DN,UDG,UDN} GraphKind; // 有向图,有向网,无向图,无向网
typedef struct AdjVexNode {
int adjvex; // 邻接顶点在顶点数组中的位序
struct AdjVexNode *next; // 指向下一个邻接顶点(下一条边或弧)
int info; // 存储边(弧)相关信息,对于非带权图可不用
} AdjVexNode, *AdjVexNodeP; // 邻接链表的结点类型
typedef struct VexNode {
VexType data; // 顶点值,VexType是顶点类型,由用户定义
struct AdjVexNode *firstArc; // 邻接链表的头指针
} VexNode; // 顶点数组的元素类型
typedef struct {
VexNode vexs[MAX_VEX_NUM]; //*vexs; 顶点数组,用于存储顶点信息
int n, e; // 顶点数和边(弧)数
GraphKind kind; // 图的类型
int *tags; // 标志数组
} ALGraph; // 邻接表类型
可调用以下基本操作:
int LocateVex(ALGraph G, VexType v); // 查找顶点v在图G中的位序
**********/
Status CreateUDG(ALGraph &G, VexType *vexs, int n,
ArcInfo *arcs, int e)
/* 创建含n个顶点和e条边的无向图G,vexs为顶点信息,arcs为边信息 */
{
if(n<0 || e<0)
return ERROR;
G.tags = (int *)malloc(sizeof(int)*n);
G.n = n;
G.e = e;
G.kind = UDG;
int k,i,j;
for(k = 0;k<G.n;k++){
G.vexs[k].data = vexs[k];
G.tags[k] = UNVISITED;
G.vexs[k].firstArc = NULL;
}
for(k = 0;k<e;k++){
i = LocateVex(G, arcs[k].v);
j = LocateVex(G, arcs[k].w);
if(i == -1 || j == -1)
return ERROR;
AdjVexNode *p;
//the first
p = (AdjVexNode*)malloc(sizeof(AdjVexNode));
p->adjvex = j;
p->info = arcs[k].inf;
p->next = G.vexs[i].firstArc;
G.vexs[i].firstArc = p;
//the second (first reverse)
p = (AdjVexNode*)malloc(sizeof(AdjVexNode));
p->adjvex = i;
p->info = arcs[k].inf;
p->next = G.vexs[j].firstArc;
G.vexs[j].firstArc = p;
}
return OK;
}