代码题
链表删除最大结点值算法(若有多个最大值,只删除第一个)
设置一个指针指向最大元素的前驱结点,一开始默认首结点为最大元素,遍历链表,找到整个链表最大结点的前驱结点,最后通过最大结点的前驱结点删除最大结点
int delMax(LNode *L){
if(L->next == NULL){
return 0;
}
LNode *p = L->next;
LNode *pre = L;
int max = p->data;
while(p != NULL){
if(p->next->data > max){
max = p->next->data;
pre = p;
}
p = p->next;
}
LNode *q = pre->next;
pre->next = q->next;
free(q);
return 1;
}
二叉树建立表达式,并用表达式求值。
二叉树建立表达式
递归遍历二叉树,在第一次访问双分支结点时,输出左括号;第二次访问结点时,输出结点值;第三次离开双分支结点时,输出右括号;并传入一个deep变量,用来控制访问根节点时不输出左右括号
void buildBds(BTNode *p, int deep){
if(p != NULL){
if(p->lchild && p->rchild && deep>1){
cout << '(';
}
buildBds(p->lchild, deep+1);
cout << p->data;
buildBds(p->rchild, deep-1);
if(p->lchild && p->rchild && deep>1){
cout << ')';
}
}
}
二叉树利用表达式求值
递归遍历二叉树,访问结点为空时返回0,访问结点为叶子结点时返回结点的值,访问结点为双分支结点时返回其左右子树进行某种运算后的结果
int bdsQz(BTNode *p){
if(p == NULL){
return 0;
}
int A = bdsQz(p->lchild);
int B = bdsQz(p->rchild);
return op(A, B, p->data);
}
int getResult(BTNode *p){
if(p == NULL){
return 0;
}
if(!p->lchild && !p->rchild){
return p->data - '0';
}
if(p->lchild && p->rchild){
int A = getResult(p->lchild);
int B = getResult(p->rchild);
return op(A, B, p->data);
}
}
有一个顺序表L,第一趟对该序列的奇数进行排序,第二趟对该序列的偶数进行排序,第三趟对奇数,第四趟对偶数...如此往复,
若有L.elem[i] > L.elem[i+1],则发生交换
(1)该算法的终止条件是什么?
(2)写出算法。
flag == 1
void oddEvenSort(SqList &L){
int flag = 0;
while(!flag){
flag = 1;
for(int i=0; i<L.length; i+=2){
if(L.elem[i] > L.elem[i+1]){
swap(L.elem[i], L.elem[i+1]);
flag = 0;
}
}
for(int j=1; j<L.length; j+=2){
if(L.elem[j] > L.elem[j+1]){
swap(L.elem(j), L.elem[j+1]);
flag = 0;
}
}
}
}
有一个二叉树,若叶子结点的关键字是偶数,利用叶子结点的右指针将所有是偶数的叶子结点连接到一个新的单链表中。
(1)简述算法思想;
(2)写出算法。
先序递归遍历二叉树,如果是偶数叶子结点且单链表的头结点为空则另单链表的头尾指针都为空,如果是偶数叶子结点且单链表的头结点不为空,则另尾指针的右孩子指针指向该节点,并让尾指针后移
void generateLink(BTNode *p, LNode *&head, LNode *&tail){
if(p != NULL){
if(!p->lchild && !p->rchild && p->data%2==0){
if(head == NULL){
head = p;
tail = p;
}else{
tail->next = p;
tail = p;
}
}
generateLink(p->lchild);
generateLink(p->rchild);
}
}
现有两个单链表A和B,其中的元素递增有序,在不破坏原链表的情况下,请设计一个算法,求这两个链表的交集,并将结果存放在链表C中。
(1)描述算法的基本设计思想;
(2)根据设计思想,给出C语言描述算法,关键之处请给出简要注释。
设置p和q两个指针用来遍历A和B两个链表,设置指针r用于向C链表中插入元素,如果p所指结点小于q所指结点,p后移;如果q所指结点小于p所指结点,q后移;如果q所指结点等于p所指结点,新申请一个结点k,让p中的结点值赋给k,把k结点插入C链表中,p和q指针分别后移
void intersection(LNode *A, LNode *B, LNode *&C){
LNode *p = A->next;
LNode *q = B->next;
LNode *r = C;
while(p!=NULL && q!=NULL){
if(p->data == q->data){
r->next = p;
r = p;
}
p = p->next;
q = q->next;
}
r->next = NULL;
}
void getCommon(LinkList A, LinkList B, LinkList &C){
C->next = NULL;
LNode *r = C;
LNode *p = A->next;
LNode *q = B->next;
while(p!=NULL && q!=NULL){
if(p->data < q->data){
p = p->next;
}else if(q->data <p->data){
q = q->next;
}else{
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = p->data;
r->next = s;
r = s;
p = p->next;
q = q->next;
}
}
}
若设二叉树T采用二叉链表存储,设计一个算法,求指定结点p的父结点。要求:
(1)描述算法的基本设计思想;
(2)根据设计思想,给出C语言描述算法,关键之处请给出简要注释。
采用后序非递归遍历的思想,利用栈做辅助结构,当出栈元素为p时,此时栈顶元素即为p的父节点
LNode *getParent(LNode *T, LNode *p){
LNode *stack[maxsize],*tag = NULL;
int top = -1;
while(T && top!=-1){
if(T != NULL){
stack[++top] = T;
T = T->lchild;
}else{
T = stack[top];
if(T->rchild && T->rchild!=tag){
T = T->rchild;
}else{
T = stack[top--];
if(T == p){
return stack[top];
}
tag = T;
T = NULL;
}
}
}
}
该问题与遍历操作类似,这里采用先序遍历的方式进行。当遍历到一个结点时,判断该结点的左右孩子是否为指定结点,如果是,则直接返回该结点即可。如果不是,则继续往后遍历,直到遍历完整棵树。所以,根据:先遍历根节点,再递归遍历左子树,最后递归遍历右子树的顺序来遍历整棵树。当树为空或找到指定结点的父节点时,即达到递归出口。
采用先序递归遍历的思想,如果结点或者p为空,直接返回空;如果结点的左子树或右子树为p,返回该结点,分别递归遍历左右子树,如果左子树不空,就返回左子树,否则就返回右子树
BTNode* getParent(BTNode* T,BTNode* p){
if(T == NULL){
return NULL;
}
if(p == NULL){
return NULL;
}
if(T->lchild == p || T->rchild == p){
return T;
}
BTNode* left = getParent(T->lchild, p);
BTNode* right = getParent(T->rchild, p);
return (left != NULL) ? left : right;
}
有一种排序算法叫做计数排序。这种排序算法对一个待排序的表(采用顺序存储)进行排序,并将排序结果存放到另一个新的表中。
必须注意的是,表中所有待排序的关键字互不相同,计数排序算法针对表中的每个元素,扫描待排序的表一趟,统计表中有多少个元素
的关键字比该元素的关键字小。假设对某一个元素,统计出数值为count,那么这个元素在新的有序表中的合适的存放位置即为count。
(1)设计实现计数排序的算法。
(2)对于有n个元素的表,比较次数是多少?
(3)与简单选择排序相比,哪种方法更好?为什么?
void countSort(int A[], int B[], int n){
int count, i, j;
for(i=0; i<n; i++){
count = 0;
for(j=0; j<n; j++){
if(A[i] > A[j]){
count++;
}
}
B[count] = A[i];
}
}
n^2
简单选择排序更好,因为简单选择排序只需要对比n^2/2次,而计数排序要对比n^2次,且计数排序每比较完一轮都要回滚到0从头比较,简单选择排序不用
回滚。
设计一个算法,判定带头结点的单链表L是否是递增的。要求:
(1)描述算法的基本设计思想
(2)根据设计思想,写出C语言描述算法,关键之处请给出简要注释。
设置相邻的两个指针p和q遍历链表,其中p在前q在后,如果p->data < q->data,则说明该链表不是递增的,否则该链表就是递增的
int judgeIsIncrease(LNode *L){
int flag = 1;
LNode *p = L->next;
while(p != NULL){
if(p->data >= p->next->data){
flag = 0;
break;
}
p = p->next;
}
return flag;
}
若二叉树采用二叉链表存储结构,试设计一个算法,求先序遍历序列中第k(1<k<二叉树中结点个数)个结点的值。假设数据类型为字符型,且二叉树中无‘$’字符。要求:
(1)描述算法的基本设计思想
(2)根据设计思想,给出C语言描述算法,关键之处请给出简要注释。
int getNode(BTNode *p, int k){
int count = 0;
if(p != null){
count++;
if(count == k){
return p->data;
}
getNode(p->lchild, k);
getNode(p->rchild, k);
}
}
int getNode(BTNode *p, int k, int &n){
if(p != NULL){
++n;
if(k == n){
cout << p->data;
return;
}
getNode(p->lchild, k, n);
getNode(p->rchild, k, n);
}
}
已知L1、L2分别为两个循环单链表(带头结点)的指针,m、n分别为L1、L2表中数据元素个数。试设计一算法,
用最快速度将两表合并成一个带头结点的循环单链表
void union(LNode *L1, LNode *L2, int m, int n){
LNode *p = L1;
LNode *q = L2;
while(p->next != L1){
p = p->next;
}
while(q->next != L2){
q = q->next;
}
p->next = L2->next;
q->next = L1;
}
试编写算法,统计一棵二叉树中所有非叶子结点的数目
void getNoLeafNum(BTNode *p, int &count){
if(p != NULL){
if(p->lchild || p->rchild){
count++;
}
getNoLeafNum(p->lchild, count);
getNoLeafNum(p->rchild, count);
}
}
将一带头结点的单链表head逆置。要求:逆置在原链表进行,不允许构造一个链表。
void reserve(LNode *&L){
LNode *p = L->next;
L->next = NULL;
while(p != NULL){
LNode *r = p->next;
p->next = L->next;
L->next = p;
p = r;
}
}
设二叉树用二叉链表表示,设计算法,求二叉树的高度。
int getHigh(BTNode *p){
if(p == NULL){
return 0;
}
int A = getHigh(p->lchild);
int B = getHigh(p->rchild);
if(A < B){
return B+1;
}else{
return A+1;
}
}
已知一个带头结点的单链表L,试编写算法:清空单链表。
void cleanLink(LNode *L){
LNode *p = L->next;
LNode *pre = L;
while(p != NULL){
LNode *r = p->next;
pre->next = r;
free(p);
p = r;
}
free(L);
}
bool clearList(LNode *&L){
LNode *p = L->next;
LNode *q;
if(p == NULL){
return true;
}
while(p != NULL){
q = p->next;
L->next = q;
free(p);
p = q;
}
free(L);
return true;
}
设二叉树用二叉链表表示,设计算法,求二叉树的度为2的结点数。
void getNodeNum(BTNode *p, int &count){
if(p != NULL){
if(p->lchild && p->rchild){
count++;
}
getNodeNum(p->lchild, count);
getNodeNum(p->rchild, count);
}
}
已知一个带头结点的单链表head,假设结点中的元素为整数,试编写算法:
按递增次序输出单链表中各个结点的数据元素,并释放结点所占的存储空间。
要求:(1)用文字给出你的算法思想;(2)不允许使用数组作为辅助空间。
先找出链表中的最小元素,输出并释放结点,然后继续找链表中的最小元素,输出并释放结点,重复这个过程,直到链表中只有一个头结点为止
void printNode(LNode *L){
LNode *p = L->next;
LNode *minp = L;
while(L->next != NULL){
while(p->next != NULL){
if(p->next->data < minp->next->data){
minp = p;
}
p = p->next;
}
cout << minp->next->data;
LNode *q = minp->next;
minp->next = q->next;
free(q);
}
free(L);
}
void delMin(LNode *&head){
while(head->next != NULL){
LNode *p = head;
LNode *minp = head;
while(p->next != NULL){
if(p->next->data < minp->next->data){
minp = p;
}
p = p->next;
}
cout << minp->next->data;
LNode *q = minp->next;
minp->next = q->next;
free(q);
}
free(head);
}
假设以带头结点的循环单链表表示队列,并且只设置一个指针rear指向队尾结点,但不设头指针,请写出相应的入队列和出队列操作。
typedef struct QueueNode{
int data;
struct QueueNode *next;
}QueueNode;
typedef LinkQueue{
QueueNode *rear;
};
void initQueue(){
QueueNode *Q = (QueueNode *)malloc(sizeof(QueueNode));
Q->rear->next = Q->rear;
}
int isEmpty(LinkQueue Q){
return Q->rear->next == Q->rear;
}
void enQueue(LinkQueue Q, int x){
QueueNode *r = (QueueNode *)malloc(sizeof(QueueNode));
r->data = x;
r->next = Q->rear->next;
Q->rear->next = r;
Q->rear = r;
}
int deQueue(LinkQueue Q, int &x){
if(Q->rear->next == Q->rear){
return 0;
}else{
QueueNode *q = Q->rear->next->next;
x = q->data
if(q = Q->rear){
Q->rear = Q->rear->next;
Q->rear->next = Q->rear;
}else{
Q->rear->next->next = Q->rear;
}
free(q);
return 1;
}
}
已知元素数据类型为整数的顺序表SL=(a1,a2,...,am,b1,b2,...,bn),试设计算法将SL中元素的两部分互换为(b1,b2,...,bn,a1,a2,...,am)。
要求:不能使用额外的数组空间。
(1)用文字给出你的算法思想;
(2)用C语言写出算法的实现。
先把该顺序表逆置,然后再把顺序表前n个元素逆置,最后把顺序表后m个元素逆置
void change(SqList &SL, int L, int R){
for(int i=L; i<(L+R)/2; i++){
swap(SL.data[L+i], SL.data[R-i]);
}
}
void func(SqList &SL, int m, int n){
change(SL, 0, m+n-1);
change(SL, 0, n-1);
change(SL, n, m+n-1);
}
对二叉链表存储的非空二叉树,从右向左依次释放所有叶子结点,释放的同时,把结点值存放到一个数组中。要求:
(1)用文字写出实现上述过程的基本思想;
(2)用C语言写出算法的实现。
先右子树,再根节点,最后左子树的顺序递归遍历二叉树,如果是叶子结点,则释放该结点并把该结点存放到A数组中
void freeLeafNode(BTNode *p,BTNode *&array[]){
int i = 0;
if(p != NULL){
if(!p->lchild &&!p->rchild){
array[i++] = p->data;
free(p);
}
freeLeafNode(p->rchild);
freeLeafNode(p->lchild);
}
}
void getArray(BTNode *p, int &A[], int &n){
if(p != NULL){
if(!p->lchild && !p->rchild){
A[n++] = p->data;
}
getArray(p->rchild, A, n);
getArray(p->lchild, A, n);
}
}