当前位置:文档之家› 数据结构课后习题

数据结构课后习题

第一章3.(1)A(2)C(3)D5.计算下列程序中x=x+1的语句频度for(i=1;i<=n;i++)for(j=1;j<=i;j++)for(k=1;k<=j;k++)x=x+1;【解答】x=x+1的语句频度为:T(n)=1+(1+2)+(1+2+3)+……+(1+2+……+n)=n(n+1)(n+2)/66.编写算法,求一元多项式p n(x)=a0+a1x+a2x2+…….+a n x n的值p n(x0),并确定算法中每一语句的执行次数和整个算法的时间复杂度,要求时间复杂度尽可能小,规定算法中不能使用求幂函数。

注意:本题中的输入为a i(i=0,1,…n)、x和n,输出为P n(x0)。

算法的输入和输出采用下列方法(1)通过参数表中的参数显式传递(2)通过全局变量隐式传递。

讨论两种方法的优缺点,并在算法中以你认为较好的一种实现输入输出。

【解答】(1)通过参数表中的参数显式传递优点:当没有调用函数时,不占用内存,调用结束后形参被释放,实参维持,函数通用性强,移置性强。

缺点:形参须与实参对应,且返回值数量有限。

(2)通过全局变量隐式传递优点:减少实参与形参的个数,从而减少内存空间以及传递数据时的时间消耗缺点:函数通用性降低,移植性差算法如下:通过全局变量隐式传递参数PolyValue(){ int i,n;float x,a[],p;printf(“\nn=”);scanf(“%f”,&n);printf(“\nx=”);scanf(“%f”,&x);for(i=0;i<n;i++)scanf(“%f ”,&a*i+); /*执行次数:n次*/p=a[0];for(i=1;i<=n;i++){ p=p+a[i]*x; /*执行次数:n次*/x=x*x;}printf(“%f”,p);}算法的时间复杂度:T(n)=O(n)通过参数表中的参数显式传递float PolyValue(float a[ ], float x, int n){float p,s;int i;p=x;s=a[0];for(i=1;i<=n;i++){s=s+a[i]*p; /*执行次数:n次*/p=p*x;}return(p);}算法的时间复杂度:T(n)=O(n)第二章1.填空:(1)在顺序表中插入或删除一个元素,需要平均移动一半元素,具体移动的元素个数与插入或删除的位置有关。

(2)线性表有顺序和链式两种存储结构。

在顺序表中,线性表的长度在数组定义时就已经确定,是静态保存,在链式表中,整个链表由“头指针”来表示,单链表的长度是动态保存。

(3)在顺序表中,逻辑上相邻的元素,其物理位置_一定_____相邻。

在单链表中,逻辑上相邻的元素,其物理位置不一定相邻。

(4)在带头结点的非空单链表中,头结点的存储位置由头指针指示,首元素结点的存储位置由头结点指示,除首元素结点外,其它任一元素结点的存储位置由其直接前趋的next域指示。

2.选择题(1) A(2) 已知L是无表头结点的单链表,且P结点既不是首元素结点,也不是尾元素结点。

按要求从下列语句中选择合适的语句序列。

a. 在P结点后插入S结点的语句序列是:D、A。

b. 在P结点前插入S结点的语句序列是:G、K、H、D、A。

c. 在表首插入S结点的语句序列是:E、L。

d. 在表尾插入S结点的语句序列是:(K)、I、A、F。

供选择的语句有:A P->next=S;B P->next= P->next->next;C P->next= S->next;D S->next= P->next;E S->next= L;F S->next= NULL;G Q= P;H while (P->next!=Q) P=P->next;I while (P->next!=NULL) P=P->next;J P= Q;K P= L;L L= S;M L= P;(3) D(4) D(5) D4. 已知顺序表L递增有序,编写一个算法,将X插入到线性表的适当位置上,以保持线性表的有序性。

void inserX(Seqlist *L,Elemtype x){int i;i=L->length-1;while(i>=0&& x<L->elem[i]){L->elem[i+1]=L->elem[i];i--;}L->length++;}7试分别以不同的存储结构实现线性表的就地逆值的算法,即在原表的存储空间中将线性表(a1,a2,…,an)逆置为(an,an-1,…,a1)。

(1)以顺序表作存储结构,设线性表存于a[1:arrsize]的前elenum个分量中。

void reverseqlist(Seqlist *L){int i;int temp;for(i=0;i<L->length/2;i++){temp=L->elem[i];L->elem[i]=L->elem[L->length-i-1];L->elem[L->length-i-1]=temp;}}(2)以单链表作存储结构。

void reverselinklist(linklist *head){Linklist *p,*q;p=head->next; head->next=NULL;while(p->next!=NULL){q=p->next;p->next=head->next;head->next=p;p=q;}}11将线性表A=(a1,a2,……am), B=(b1,b2,……bn)合并成线性表C,C=(a1,b1,……am,bm,bm+1,…….bn)m<=n,或C=(a1,b1, ……an,bn,an+1,……am) m>n,线性表A、B、C以单链表作为存储结构,且C表利用A表和B表中的结点空间构成。

注意:单链表的长度值m和n均未显式存储。

【解答】算法如下:LinkList merge(LinkList A,LinkList B,LinkList C){Node *pa,*qa,*pb,*qb,*p;pa=A->next;/*pa表示A的当前结点*/pb=B->next;p=A;/ *利用p来指向新连接的表的表尾,初始值指向表A的头结点*/while(pa!=NULL&&pb!=NULL)/*利用尾插法建立连接之后的链表*/{qa=pa->next;qb=qb->next;p->next=pa;/*交替选择表A和表B中的结点连接到新链表中;*/p=pa;p->next=pb;p=pb;pa=qa;pb=qb;}if(pa!=NULL)p->next=pa;/*A的长度大于B的长度*/if(pb!=NULL)p->next=pb;/*B的长度大于A的长度*/C=A;Return(C);}第三章1 B2 C3 C8假设表达式由单字母变量和双目四则运算构成。

试写一个算法,将一个通常书写形式且书写正确的表达式转为逆波兰式。

【分析】算法的思想:所有的变量在逆波兰式中出现的先后顺序和在原表达式中出现的相同,因此只需要设立一个"栈",根据操作符的"优先级"调整它们在逆波兰式中出现的顺序。

#include <stdio.h>#include <malloc.h>#define STACK_INIT_SIZE 100#define STACK_INCREAMENT 10typedef struct { //栈char *base;char *top;int stackSize;} Stack;void initStack(Stack &stack) { //初始化栈stack.base = stack.top = (char *)malloc(sizeof(char) * STACK_INIT_SIZE);stack.stackSize = STACK_INIT_SIZE;}void push(Stack &S, char p) { //入栈if(S.top - S.base >= S.stackSize) {S.base=(char*)realloc(S.base,(S.stackSize+STACK_INCREAMENT)*sizeof(char));S.top = S.stackSize + S.base;S.stackSize += STACK_INCREAMENT;}*S.top++ = p;}void pop(Stack &stack, char &p) { //出栈if(stack.base == stack.top) {p = NULL; return ;}p = *--stack.top;}char getTop(Stack stack) { //获得栈顶元素if(stack.base == stack.top) return NULL;return *(stack.top - 1);}bool isAlpha(char p) { //判断是不是字母return (p >= 'a' && p <= 'z') || (p >= 'A' && p <= 'Z') ? true : false;}int precede(char a, char b) {switch (a) {case '/' :case '*' : return 1; break;case '+' :case '-' :switch(b) {case '/' :case '*' : return -1; break;default : return 1;}break;default :switch(b) {case '#' : return 0; break;default : return -1;}}}void NiBoLan(char *str, char *newStr) { //转换成逆波兰式Stack stack;initStack(stack);char *p, *q, c;p = str; q = newStr;push(stack, '#');while(*p) {if(isAlpha(*p)) *q++ = *p;else {c = getTop(stack);if(precede(*p, c) > 0) push(stack, *p);else {while(precede(getTop(stack), *p) >= 0 && *p) {pop(stack, c); *q++ = c;}push(stack, *p);}}p ++;}}void main() {char str[100];char newStr[100];int i;for(i=0; i<100; i++) str[i] = newStr[i] = '\0';printf("请输入表达式:\n"); scanf("%s", str);NiBoLan(str, newStr);printf("其对应的逆波兰式为:%s\n", newStr);}10 要求循环队列不损失一个空间全部都能得到利用,设置一个标志tag,以tag为0或1来区分头尾指针相同时的队列状态的空与满,请编写与此相应的入队与出队算法。

相关主题