没有合适的资源?快使用搜索试试~ 我知道了~
首页数据结构课后题答案 高等教育出版社
数据结构课后题答案 高等教育出版社
需积分: 48 484 浏览量
更新于2023-03-16
评论 3
收藏 4.14MB DOC 举报
这是早期高等教育出版社出版的,很精华的,是老师亲自作出来的,例题也很经典哦!
资源详情
资源评论
资源推荐

第一章 绪论(参考答案)
1.3 (1) O(n)
(2) (2) O(n)
(3) (3) O(n)
(4) (4) O(n
1/2
)
(5) (5) 执行程序段的过程中,x,y 值变化如下:
循环次数 x y
0(初始) 91 100
1 92 100
2 93 100
…… …… ……
9 100 100
10 101 100
11 91 99
12 92 100
…… …… ……
20 101 99
21 91 98
…… …… ……
30 101 98
31 91 97
到 y=0 时,要执行 10*100 次,可记为 O(10*y)=O(n)
1.5 2
100
, (2/3)
n
,
log
2
n , n
1/2
,
n
3/2
, (3/2)
n
, n
log
2
n
, 2
n
,
n! , n
n
第二章 线性表(参考答案)
在以下习题解答中,假定使用如下类型定义:
(1)顺序存储结构:
#dene MAXSIZE 1024
typedef int ElemType;// 实际上,ElemType 可以是任意类型
typedef struct
{ ElemType data[MAXSIZE];
int last; // last 表示终端结点在向量中的位置
}sequenlist;
(2)链式存储结构(单链表)
typedef struct node
{ElemType data;
struct node *next;
}linklist;
(3)链式存储结构(双链表)
typedef struct node
{ElemType data;
struct node *prior,*next;
}dlinklist;
(4)静态链表
typedef struct
{ElemType data;
int next;
}node;

node sa[MAXSIZE];
2.1 头指针:指向链表的指针。因为对链表的所有操均需从头指针开始,即头指针具有标
识链表的作用,所以链表的名字往往用头指针来标识。如:链表的头指针是 la,往往简称
为“链表 la”。
头结点:为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加
的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,
这只是副产品),其指针域指向头结点。这样在插入和删除中头结点不变。
开始结点:即上面所讲第一个元素的结点。
2.2 只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。
2·3
void insert(ElemType A[],int elenum,ElemType x)
// 向量 A 目前有 elenum 个元素,且递增有序,本算法将 x 插入到向量 A 中,并保持向量
的递增有序。
{ int i=0,j;
while (i<elenum && A[i]<=x) i++; // 查找插入位置
for (j= elenum-1;j>=i;j--) A[j+1]=A[j];// 向后移动元素
A[i]=x; // 插入元素
} // 算法结束
2·4
void rightrotate(ElemType A[],int n,k)
// 以向量作存储结构,本算法将向量中的 n 个元素循环右移 k 位,且只用一个辅助空间。
{ int num=0; // 计数,最终应等于 n
int start=0; // 记录开始位置(下标)
while (num<n)
{ temp=A[start]; //暂存起点元素值,temp 与向量中元素类型相同
empty=start; //保存空位置下标
next=(start-K+n) %n; // 计算下一右移元素的下标
while (next !=start)
{ A[empty]=A[next];// 右移
num++; // 右移元素数加 1
empty=next;
next=(next-K+n) %n; // 计算新右移元素的下标
}
A[empty]=temp; // 把一轮右移中最后一个元素放到合适位置
num++;
start++; // 起点增 1,若 num<n 则开始下一轮右移。
}
} // 算法结束
算法二
算法思想:先将左面 n-k 个元素逆置,接着将右面 k 个元素逆置,最后再将这 n 个元素
逆置。
void rightrotate(ElemType A[],int n,k)
// 以向量作存储结构,本算法将向量中的 n 个元素循环右移 k 位,且只用一个辅助空间。
{ ElemType temp;
for(i=0;i<(n-k)/2;i++) //左面 n-k 个元素逆置
{temp=A[i]; A[i]=A[n-k-1-i]; A[n-k-1-i]=temp; }
for(i=1;i<=k;i++) //右面 k 个元素逆置
{temp=A[n-k-i]; A[n-k-i]=A[n-i]; A[n-i]=temp; }
for(i=0;i<n/2;i++) //全部 n 个元素逆置
{temp=A[i]; A[i]=A[n-1-i]; A[n-1-i]=temp; }
} // 算法结束

2·5
void insert(linklist *L,ElemType x)
// 带头结点的单链表 L 递增有序,本算法将 x 插入到链表中,并保持链表的递增有序。
{ linklist *p=L->next, *pre=L,*s;
// p 为工作指针,指向当前元素,pre 为前驱指针,指向当前元素的前驱
s=(linklist *)malloc(sizeof(linklist));//申请空间,不判断溢出
s->data=x;
while (p && p->data<=x) {pre=p; p=p->next;} // 查找插入位置
pre->next=s; s->next=p; // 插入元素
} // 算法结束
2·6
void invert(linklist *L)
// 本算法将带头结点的单链表 L 逆置。
//算法思想是先将头结点从表上摘下,然后从第一个元素结点开始,依次前插入以 L 为头
结点的链表中。
{ linklist *p=L->next,*s;
// p 为工作指针,指向当前元素,s 为 p 的后继指针
L->next=null;//头结点摘下,指针域置空。算法中头指针 L 始终不变
while (p)
{s=p->next; // 保留后继结点的指针
p->next=L->next; // 逆置
L->next=p;
p=s; // 将 p 指向下个待逆置结点
}
} // 算法结束
2·7
(1) int length1(linklist *L)
// 本算法计算带头结点的单链表 L 的长度
{ linklist *p=L->next; int i=0;
// p 为工作指针,指向当前元素,i 表示链表的长度
while (p)
{ i++; p=p->next; }
return(i);
} // 算法结束
(2) int length1(node sa[MAXSIZE])
// 本算法计算静态链表 s 中元素的个数。
{ int p=sa[0].next, i=0;
// p 为工作指针,指向当前元素,i 表示元素的个数,静态链指针等于-1 时链表结束
while (p!=-1)
{ i++; p=sa[p].next; }
return(i);
} // 算法结束
2·8
void union_invert(linklist *A,*B,*C)
// A 和 B 是两个带头结点的递增有序的单链表,本算法将两表合并成
// 一个带头结点的递减有序单链表 C,利用原表空间。
{ linklist *pa=A->next,*pb=B->next,*C=A,*r;
// pa,pb 为工作指针,分别指向 A 表和 B 表的当前元素,r 为当前逆置
//元素的后继指针, 使逆置元素的表避免断开。

//算法思想是边合并边逆置,使递增有序的单链表合并为递减有序的单链表。
C->next=null;//头结点摘下,指针域置空。算法中头指针 C 始终不变
while (pa && pb) // 两表均不空时作
if (pa->data<=pb->data) // 将 A 表中元素合并且逆置
{ r=pa->next; // 保留后继结点的指针
pa->next=C->next; // 逆置
C->next=pa;
pa=r; // 恢复待逆置结点的指针
}
else // 将 B 表中元素合并且逆置
{ r=pb->next; // 保留后继结点的指针
pb->next=C->next; // 逆置
C->next=pb;
pb=r; // 恢复待逆置结点的指针
}
// 以下 while (pa)和 while (pb)语句,只执行一个
while (pa) // 将 A 表中剩余元素逆置
{ r=pa->next; // 保留后继结点的指针
pa->next=C->next; // 逆置
C->next=pa;
pa=r; // 恢复待逆置结点的指针
}
while (pb) // 将 B 表中剩余元素逆置
{ r=pb->next; // 保留后继结点的指针
pb->next=C->next; // 逆置
C->next=pb;
pb=r; // 恢复待逆置结点的指针
}
free(B);//释放 B 表头结点
} // 算法结束
2·9
void deleteprior(linklist *L)
// 长度大于 1 的单循环链表,既无头结点,也无头指针,本算法删除*s 的前驱结点
{ linklist *p=s->next,*pre=s; // p 为工作指针,指向当前元素,
// pre 为前驱指针,指向当前元素*p 的前驱
while (p->next!=s) {pre=p; p=p->next;} // 查找*s 的前驱
pre->next=s;
free(p); // 删除元素
} // 算法结束
2·10
void one_to_three(linklist *A,*B,*C)
// A 是带头结点的的单链表,其数据元素是字符字母、字符、数字字符、其他字符。本算
法//将 A 表分成
// 三个带头结点的循环单链表 A、B 和 C,分别含有字母、数字和其它符号的同一类字符,
利用原表空间。
{ linklist *p=A->next,r;
// p 为工作指针,指向 A 表的当前元素,r 为当前元素的后继指针,使表避免断开。
//算法思想是取出当前元素,根据是字母、数字或其它符号,分别插入相应表中。
B=(linklist *)malloc(sizeof(linklist));//申请空间,不判断溢出
B->next=null; // 准备循环链表的头结点
C=(linklist *)malloc(sizeof(linklist));//申请空间,不判断溢出

C->next=null; // 准备循环链表的头结点
while(p)
{ r=p->next; // 用以记住后继结点
if (p->data>=’a’&&p->data<=’z’||p->data>=’A’&& p->data<=’Z’)
{p-> next=A->next; A->next=p;} // 将字母字符插入 A 表
else if (p->data>=’0’&&p->data<=’9’)
{p->next=B->next; B->next=p;} // 将数字字符插入 B 表
else {p->next=C->next; C->next=p;}// 将其它符号插入 C 表
p=r; // 恢复后继结点的指针
}//while
} // 算法结束
2·11
void locate(dlinklist *L)
// L 是带头结点的按访问频度递减的双向链表,本算法先查找数据 x,
// 查找成功时结点的访问频度域增 1,最后将该结点按频度递减插入链表中适当位置。
{ linklist *p=L->next,*q;
//p 为工作指针,指向 L 表的当前元素,q 为 p 的前驱,用于查找插入位置。
while (p && p->data !=x) p=p->next; // 查找值为 x 的结点。
if (!p) return (“不存在值为 x 的结点”);
else { p->freq++; // 令元素值为 x 的结点的 freq 域加 1 。
p->next->prir=p->prior; // 将 p 结点从链表上摘下。
p->prior->next=p->next;
q=p->prior; // 以下查找 p 结点的插入位置
while (q !=L && q->freq<p-freq) q=q->prior;
p->next=q->next; q->next->prior=p;// 将 p 结点插入
p->prior=q; q->next=p;
}
} // 算法结束
第三章 栈和队列(参考答案)
// 从数据结构角度看,栈和队列是操作受限的线性结构,其顺序存储结构
// 和链式存储结构的定义与线性表相同,请参考教材,这里不再重复。
3.1 1 2 3 4 2 1 3 4 3 2 1 4 4 3 2 1
1 2 4 3 2 1 4 3 3 2 4 1
1 3 2 4 2 3 1 4 3 4 2 1
1 3 4 2 2 3 4 1
1 4 3 2 2 4 3 1
设入栈序列元素数为 n,则可能的出栈序列数为 C
2n
n
=(1/n+1)*(2n!/(n!)
2
)
3.2 证明:由 j<k 和 p
j
<p
k
说明 p
j
在 p
k
之前出栈,即在 k 未进栈之前 p
j
已出栈,之后 k 进
栈,然后 p
k
出栈;由 j<k 和 p
j
>p
k
说明 p
j
在 p
k
之后出栈,即 p
j
被 p
k
压在下面,后进先
出。由以上两条,不可能存在 i<j<k 使 p
j
<p
k
<p
i
。也就是说,若有 1,2,3 顺序入栈,
不可能有 3,1,2 的出栈序列。
3.3 void sympthy(linklist *head, stack *s)
//判断长为 n 的字符串是否中心对称
{ int i=1; linklist *p=head->next;
while (i<=n/2) // 前一半字符进栈
{ push(s,p->data); p=p->next; }
if (n % 2 !==0) p=p->next;// 奇数个结点时跳过中心结点
while (p && p->data==pop(s)) p=p->next;
if (p==null) printf(“链表中心对称”);
else printf(“链表不是中心对称”);
} // 算法结束
3.4
int match()
剩余44页未读,继续阅读









安全验证
文档复制为VIP权益,开通VIP直接复制

评论0