1、算法有哪些特征?怎样评价一个算法?答:算法有五个特性,分别为确定性、有穷性、可行性、0个或多个输入、1个或多个输出。
评价算法可以从时间复杂度和空间复杂度来衡量其效率。
2、头指针和头结点的类型不一样吗?答:略3、什么是静态分配?什么是动态分配?答:①静态分配是指变量或数据的空间是在程序加载时分配,其空间大小在程序运行不会改变,空间的分配和释放不能通过代码控制;②动态分配是指数据空间是在程序运行过程中分配的,空间的释放也是在程序运行过程中通过代码完成。
4、在单链表中,什么是头结点?什么是头指针?什么是首元结点?答:头结点:为保护头指针而在链表中增设的结点,其数据域一般不用,指针域用以存储首元结点的地址;头指针:链表访问的起点,在带头结点的单链表中存储头结点的地址,在不带头结点的单链表中存储首元结点的地址;首元结点:第一个元素结点。
头指针头结点首元节点(头指针可以指向头结点或者首元节点)5、在单链表、双向链表和单循环链表中,若仅知道指针P指向某结点,不知道头指针,能否将结点*P从相应的链表中删去?若可以,其时间复杂度为多少?答:不管是什么链表,要将结点P从链表中删除均需找到P的前驱结点。
如果是单链表,在不知头指针的条件下无法找到前驱,故无法删除;如果是双向链表,则可通过P的前驱指针找到其前驱结点,故可直接删除,无需查找,其时间复杂度为O(1);如果是循环链表,则可通过指针移动找到其前驱,其时间复杂度为O(N)。
6、顺序栈和链栈哪一种更好?为什么?答:略7、递归算法效率是否非常低?答:略8、在顺序队列操作中,什么是“假溢出”现象?怎样解决这种现象?答:在顺序队列中,可能会因为频繁的入队和出队操作造成队列有剩余空间却无法完成入队操作的现象,即为“假溢出”现象。
可采用循环队列来解决此问题,通过求余运算将队列从逻辑上构造成一个环状结构。
9、循环队列的优点是什么?如何判定它的空和满?答、循环队列可以解决顺序队列中出现的假溢出现象,但仅凭头尾指针是否相等无法区分队空和队满。
此时有两种方案可以解决此问题。
一是使用标识符,如length来记录队列元素个数,当length==0时队列为空,当length==MAXQSIZE 时队列已满;另一种方案是少用一个元素空间,约定以队列头指针在队尾指针的下一个位置作队列呈满状态的标志,头尾指针相等时队列为空。
10、下述算法的功能是什么?LinkList Demo(LinkList L){ListNode *P,*Q;if (L&&L->next){Q=L;L=L->next;P=L;While(P->next) P=P->next;P->next=Q;Q->next=NULL;}return L;}答:将链表的头结点移至链表末尾,原链表首元结点作为新的头结点。
11、下述算法的功能是什么?…………SqQueue Q1,Q2;int x,I,m=0;…………while(!QueueEmpty(Q1)){x=DeQueue(Q1);EnQueue(Q2,x);m++;}for(I=0;I<m;I++){x=DeQueue(Q2);EnQueue(Q1,x);EnQueue(Q2,x);}…………答:将队列Q1的元素复制到队列Q2中。
12、下述算法的功能是什么?void demo2(SqQueue *Q){int x;SqStack S;InitStack(&S);while(!QueueEmpty(Q)){x=DeQueue(Q);push(S,x);}while(!StackEmpty(S)){x=pop(S);Enqueue(Q,x);}}答:将队列Q的元素按逆序存储,其第一个元素的起始位置将下移一段距离,此距离为队列的长度。
13、指出下列程序段的功能是什么?1)void demo1(SqStack *S){int I,arr[64],n=0;while(!StackEmpty(S))arr[n++]=pop(S);for(I=0;I<n;I++)push(s,arr[I]);}答:将栈中元素按逆序存放。
14、设计算法,实现顺序表的选择排序(元素类型为整型)void SelectSort(SqList L){for(i=0;i<L.Length-1;i++){min=i;for(j=i+1;j<L.length;j++)if(L.elem[j]<L.elem[min]) min=j;if(min!=i){L.elem[min]<->L.elem[i];}}}15、设计算法,实现顺序表的冒泡排序(元素类型为整型)void BubbleSort(SqList L){change=1;for(i=1;i<L.Length&&change==1;i++){change=0;for(j=0;j<L.length-i;j++)if(L.elem[j]<L.elem[j+1]){change=1;L.elem[j]<->L.elem[j+1];}}}16、设计算法,实现单向链表的就地逆置。
void ReverseList(LinkList L){p=L->next;L->next=NULL;while(p){q=p->next;p->next=L->next;L->next=p;p=q;}}17、设计算法,实现顺序表的就地逆置。
VOID ReverseList (SqList *L){ ElemType t;int i,j;for(i=0;i<=L->length/2-1;i++){ j=L->lenght-1-i;t=L->elem[i];L->elem[i]=L->elem[j];L->elem[j]=t;}}18、设顺序表L是一个递增有序表,试写一算法将X插入到L中,并使L仍是一个有序表。
void InsertSortedList(SqList *L,ElemType e){if(L->length >= L->listsize){L->elem=(ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));if(!L->elem) exit(OVERFLOW);L->listsize+=LISTINCREMENT;}for(i=L->length-1;i>=0;i--)if(L->elem[i] > e) L->elem[i+1]=L->elem[i];else break;L->elem[i]=e;L->length++;}19、试对顺序表(元素类型为整型)写出折半查找算法,并分析算法时间复杂度。
n┚+1)(时间复杂度为┖log2int BinarySearch(SqList L,ElemType key){high=0;low=L.length-1;while(low<=high){middle=(low+high)/2;if(L.elem[middle]==key)beak;else if(L.elem[middle]<key)low=middle+1;elsehigh=middle-1;}if(low<=high)//找到时,返回位置return low;elsereturn -1;//未找到时,返回-1}20、已经L1和L2分别指向两个单链表的头结点,且已知其长度分别为M和N,试写一算法将两个链表连接在一起,并分析算法的时间复杂度。
LinkList ConnectList(LinkList L1,LinkList L2,int m,int n){MinL=(m<n)?L1:L2;MaxL=(m<n)?L2:L1;p=MinL;while(p->next) p=p->next;p->next=MaxL->next;free(MaxL);return MinL;}时间复杂度:O(min(m,n))//最小的那个链表的长度21、写一算法将单链表中值重复的结点删除,使所得的结果表中各结点值均不相同。
void DeleteSameNode(LinkList L){p=L->next;//p为基准结点while(p->next){//删除链表中其余与p->data相等的结点;r=p;//r记录要删除节点的前一个节点q=p->next;//q为待比较结点,初始为基准结点的后继结点;r总是指向q的前驱,使用该指针的目的为方便删除结点qwhile(q){//判断p->data和q->data是否相等,如相等,则删除结点q if(q->data==p->data){r->next=q->next;free(q);q=r->next;}else{r=r->next;q=q->next;}}p=p->next;}}22、假设在长度大于1的单循环链表中,既无头结点也无头指针,S为指向表中某个结点的指针,试编写算法删除结点S的直接前驱结点。
void DeleteNode(LNode *S){LNode *p,*q;p=S;while(p->next!=S){q=p; p=p->next;}q->next=S;free(p);}23、试写一个判别表达式开、闭括号是否配对出现的算法;Status Match(SqStack *S,char a[]){int i; char e;for(i=0;i<strlen(a);i++){if(a[i]==’( ’ || a[i] == ‘[‘) Push(S,a[i]);else{if(a[i]==’)’)if(S->top==S->base||*(S->top-1 )= =’[‘)return FALSE//栈不为空并且栈首是[//栈头==栈尾的时候,栈就为空else Pop(S,&e);if(a[i]==‘]’)if(S->top==S->base||*(S->top-1)==’(‘] return FALSE;else Pop(S,&e);}}if (S->top==S->base) return TRUE;else return FALSE;}24、试写一算法,识别依次读入的一个以@为结束符的字符序列是否是形如“序列1&序列2”的字符序列,其中序列1和序列2均不包含字符“&”,且序列2是序列1的逆序;如“A+B&B+A”是这种序列,而“1+3&3-1”则不是这种序列;Status Match(){InitStack(S);ch=getchar();while(ch!=’&’) {if ch==’@’ return FALSE;Push(S,ch); ch=getchar();}ch=getchar();while(ch!=’@’){if(ch==’&’) return FALSE;if(S->top==S->base) return FALSE;if(*(S->top-1)!=ch) return FALSE;Pop(S,&e); ch=getchar();}if(S->top!=S->base) return FALSE;else return TRUE;//栈为空了}25、回文是指正读和反读均相同的字符序列,如“ABBA”和“ABDBA”等均是回文,但“GOOD”则不是回文,试写一算法判定给定字符序列是否为回文;Status Match(){SqStack S; LinkQueue Q;char ch;InitStack(S); InitQueue(Q);ch=getchar();while(ch!=’@’){push(S,ch); EnQueue(Q,ch);}while(!QueueEmpty(Q)){ DeQueue(Q,&ch1); Pop(S,&ch2); if(ch1!=ch2) return FALSE;}return TRUE;}26、假设循环队列定义为:以域变量rear和length分别指示循环队列中队尾元素的位置和内含元素的个数,试给出此循环队列的队满和队空条件,并写出相应的入队和出队算法;#define MAXQSIZE 100typedef struct{QElemType base[MAXQSIZE];int rear,length;} CirQueue;//循环队列的定义Status EnQueue(CirQueue *Q,QElemType e){if(Q->length==MAXQSIZE)//队满条件return ERROR;Q->base[Q->rear]=e;Q->rear++;Q->length++;return OK;}Status DeQueue(CirQueue *Q,QElemType *e)//出队的话只用改length- -;{if(Q->length==0)//队空条件return ERROR;int front=(Q->rear-Q->length+MAXQSIZE)%MAXQSIZE;*e=Q->base[front];//返回出队元素,就需要上面两句句Q->length--;return OK;}27、试写出双向栈的判定条件以及相应的入栈和出栈算法;#define MAXSIZE 100typedef struct{SElemType base[MAXSIZE];int top1,top2;}DblStack;//双向栈定义Status Push(DblStack *S,SElemType e,int index)//index标志插栈1还是2 {if(S->top1>S->top2) //栈满条件return ERROR;if(index==0)S->base[S->top1++]=e;//base相当于一个数组,存栈中的数据elseS->base[S->top2--]=e;return OK;}Status Pop(DblStack *S,SElemType *e,int index){if(index==0){if(S->top1==0) //栈1的栈空条件return ERROR;*e=S->base[--S->top1];return OK;}else{if(S->top2==MAXSIZE-1) //栈2的栈空条件return ERROR;*e=S->base[++S->top2];return OK;}return FALSE;}29、母牛问题:有一头母牛从第4年起开始每年生一头小母牛,每头小母牛也是从第4年起每年生一头小母牛,部N年后共有多少头母牛?年份 1 2 3 4 5 6 7 8 9 10头数 1 1 1 2 3 4 6 9 13 19归纳出数学模型1 (N<=3)F(N)= F(N-1)+F(N-3) (N>3) 其中F(N-1)为上一年母牛头数F(N-3)第N年能生养出小母牛的母牛头数.int Func(int n){if(n<=3) return 1;return Func(n-1)+Func(n-3);}30、分别写出长度为N的数组的最大值的递归算法。