1.求出二叉树的根结点到给定某结点之间的路径(即求该结点的所有祖先结点)。
要求:
1)给出算法思想
由于二叉树非递归后序遍历的特点可知,当遍历到某一个结点时,栈中的所有结点都是该结点的祖先,而从栈底到栈顶正是从根结点到该结点的路径,所以在非递归后序遍历的算法上进行修改即可。
2)写出二叉树采用的存储结构代码(即二叉链式存储结构)
typedef struct BiTNode {
ElemType data;
struct BiTNode *lchild,*rchild;
} BTNode,BiTree;
3)采用c或c++语言描述算法,关键之处给出注释
#define MaxSize 100
//b根结点,s给定结点
int AncestoPath(BTNode *b,BTNode *s) {
BTNode* st[MaxSize];
BTNode *p;
int i,flag,top=-1;
while(b!=NULL) {
st[++top]=b;
b=b->lchild;
}
p=NULL;//当前结点的前一个已访问结点
flag=1;//设置b的访问标记为已访问
while(top!=-1&&flag) {
b=st[top];
//右子树不存在或该点已被访问
if(b->rchild==p) {
if(b==s) {
for(i=0; i<=top; ++i) {
printf("%c",st[i]->data);
}
return 1;
} else {
top--;
p=b;
}
} else {
b=b->rchild;
flag=0;
}
}
return 0;
}
2.设有n个不全为负的整型元素存储在一维数组A[n]中,它包含很多连续的子数组,求数组A的子数组之和的最大值。
例如A={1,-2,3,10,-4,7,2,-5},最大子数组为{3,10,-4,7,2},因此输出为18。
要求:
1)给出算法思想
对数组进行一次遍历,那选取一个元素是否加入子段的方法如下:若一个子段和为b,在判断是否加入下个元素a[i+1]时可用b+a[i+1]>=0,若大于等于0则符合条件。并用sum存储目前最大子段和,每加入一个新元素就比较新的子段和与sum的大小,r若b>sum,就使sum=b。而若没有,则继续把下一个元素加入字段,直至遍历完一次。
2)采用c或c++语言描述算法,关键之处给出注释
int maxSum(int n,int *a) {
int sum=0,b=0;
for(int i=0; i<n; i++) {
if(b>0)
b=b+a[i];
else
b=a[i];
if(b>sum)
sum=b;
}
return sum;
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(n),空间复杂度为O(1)。
3.将一个数组最开始的若干元素搬到数组的末尾,称为数组的旋转。输出一个已排好序的数组的一个旋转,求该旋转数组的最小元素。
例如:数组{3,4,5,1,2}为有序数组{1,2,3,4,5}的一个旋转数组,该数组的最小值为1。
要求:
1)给出算法思想
旋转之后的数组实际上可以划分为两个排序好的子数组,且前面的子数组的元素都大于等于后面子数组的元素,而最小的元素刚好是这两个数组的分界线。因此比前一个元素和后一个元素都大的元素即为最小元素。
2)采用c或c++语言描述算法,关键之处给出注释
int findMinNumber(int *numbers,int length) {
if(numbers==0||length<0) {
return 0;
}
int i;
for(i=1; i<length; i++) {
if(numbers[i-1]>numbers[i]&&numbers[i]<numbers[i+1])
return numbers[i];
}
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(n),空间复杂度为O(1)。
4.已知线性表(a1,a2,a3···an)存放在一维数组A中。将所有奇数号元素移到所有偶数好元素前,并且不改变奇数号(或偶数号)元素之间的相对顺序。
要求:
1)给出算法思想
先将偶数号元素复制到一个辅助空间,同时整理数组剩下的奇数号元素,最后将辅助空间中的元素复制到数组的后半部分
2)采用c或c++语言描述算法,关键之处给出注释
void swap(ElemType A[],int n) {
ElemType B[];
//假设数组从1开始存放
int i=1,k=1;
while(i<=n) {
//奇数在前,偶数在后
if(i%2==0) {
B[k++]=A[i++];
} else {
A[i-k+1]=A[i++];
}
}
int length=k-1;
i=i-length;
for(k=1; k<=length; k++) {
A[i++]=B[k];
}
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(n),空间复杂度为O(n)。
5.设有m+n个元素顺序存放在数组A[1···m+n]中,前m个元素递增有序,后n个元素递增有序,设计算法使整个顺序表递增有序。
要求:
1)给出算法思想
将数组的前m个元素和后n个元素分别视为一个归并段,增加一个临时数组B[1···m+n]存储临时归并结果。设置指针k1,k2分别指向两个归并段的首元素,再设置指针k3指向临时数组的下一个结果位置。若1<=k1<=m&&m+1<=k2<=m+n,比较两个归并段指针所指元素的大小;否则将剩余元素全部复制到数组B中。最后把数组B复制到数组A。
2)采用c或c++语言描述算法,关键之处给出注释
void merge(int A[]) {
int B[m+n];
int k1,k2,k3;
k1=1;
k2=m+1;
k3=1;
//比较两归并段
while(k1<=m&&k2<=m+n) {
if(A[k1]<A[k2])
B[k3++]=A[k1++];
else
B[k3++]=A[k2++];
}
//剩余元素复制到B
while(k1>m&&k2<=m+n)
B[k3++]=A[k2++];
while(k2>m+n&&k1<=m)
B[k3++]=A[k1++];
//把临时数组B复制到A中
for(int i=1; i<=m+n; i++)
A[i]=B[i];
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(m+n),空间复杂度为O(m+n)。
6.已知长度为n(n>1)的单链表,表头指针为L,结点结构由data和next两个域构成,其中data域为字符型。设计算法判断该链表是否中心对称。
例如:xyx、xxyyxx
要求:
1)给出算法思想
借助辅助栈,将链表的前一半元素依次进栈(注意n为奇数时要特殊处理),在处理链表的后一半元素时,每访问一个就从栈中弹出一个元素,两元素比较,若相等,则继续将链表的下一个元素与栈中再弹出的元素进行比较,直至链表到尾。若比较过程中存在不等时,得出链表非中心对称的结论;若栈时空栈,得出链表中心对称的结论。
2)采用c或c++语言描述算法,关键之处给出注释
typedef struct LNode {
char data;
strcut LNode *next;
}*LinkList;
bool strSame(LinkList L,int n) {
Stack s;
initstack(s);
LNode *q,*p=L->next;
for(int i=1; i<n/2; i++) {
push(p);
p=p->next;
}
if(n%2==1)
p=p->next;
while(p!=NULL) {
q=pop(s);
if(q->data==p->data)
p=p->next;
else
break;
}
if(empty(s))
return true;
else
return false;
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(n),空间复杂度为O(n)。
7.在数组中,某个数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。
例如:在数组{2,4,1,16,7,5,11,9}中,数对之差的最大值是11,是16减去5的结果。
要求:
1)给出算法思想
先选取第一个数为整个数组的最大值max,选取第一个数与第二个数的差为最大差maxDiff,然后通过循环找到满足numbers[h]减去numbers[i]之差是最大的,此时h<i,0<=i<n,并且numbers[h]时numbers[i]之前元素中的最大值。设置变量currentDiff与maxDiff比较,不断更新maxDiff的值。
2)采用c或c++语言描述算法,关键之处给出注释
int maxDiff(int numbers[],unsigned length) {
if(numbers==NULL || length<2) return 0;
int max=numbers[0];
int maxDiff=max-number[1];
for(i=2; i<length; i++) {
if(numbers[i]>max)
max=numbers[i];
int currentDiff=max-numbers[i];
if(currentDiff>maxDiff)
maxDiff=currentDiff;
}
return maxDiff;
}
3)说明时间复杂度和空间复杂度
时间复杂度为O(n),空间复杂度为O(1)。
8.求指定的第k层的叶子结点的个数。
要求:
1)给出算法思想
采用层次遍历思想,只需在层次遍历上添加记录当前层次的功能。没有达到目标层时,把该结点的孩子结点入队;达到目标层时,统计叶子结点个数。
2)写出二叉树采用的存储结构代码(即二叉链式存储结构)
typedef struct BiTNode {
ElemType data;
struct BiTNode *lchild,*rchild;
} BTNode,*BiTree;
3)采用c或c++语言描述算法,关键之处给出注释
int leafKLevel(BiTree T,int k) {
if(!T) return 0;//空树
Queue Q;
//第k层sum叶子结点的个数,last为一层中最后一个结点在队列的位置
int sum=0,last=0;
InitQueue(Q);
BiTree p;
int level=1;
EnQueue(Q,T);
while(level<=k) {
DeQueue(Q,p);//先出队,再front+1
if(p->lchild)
EnQueue(Q,p->lchild);//每次先入队,再rear+1
if(p->rchild)
EnQueue(Q,p->rchild);
if(level==k) {
if(p->lchild==NULL&&p->rchild==NULL) {
sum++;
}
}
//判断这一层的元素是否全部出队
if (Q.front > last) {
last = Q.rear-1;
level++;
}
}
return sum;
}