南航829数据结构历年真题答案

2013年真题

第四题:

问题描述:已知有两个带头结点的单链表A和B,元素值递增有序,编写函数调整删减链表,使A链表的元素值为A、B的交集,并成为一个递减有序的单链表,要求写出算法思想以及相应代码:
代码

//2013数据结构第四题
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    struct LNode *next;
} *LinkList,LNode;
void GetCommon(LinkList A,LinkList B)
{
	LinkList p=A->next,q=B->next,s=NULL;
	A->next=NULL;
	while(p&&q) 
	{
		if(p->data<q->data)
		{
			s=p->next;
			free(p);
			p=s;
		}
		else if(p->data>q->data)
		{
			q=q->next;//B链表不进行删除 
		}
		else{
			s=p->next;
			p->next=A->next;
			A->next=p;
			p=s;
		} 
	}
	while(p)
	{
		s=p->next;
		free(p);
		p=s;
	}
} 
int main()
{
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	LinkList a1= (LinkList) malloc(sizeof(LNode) );
	LinkList a2= (LinkList) malloc(sizeof(LNode) );
	LinkList a3= (LinkList) malloc(sizeof(LNode) );
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	LinkList b1= (LinkList) malloc(sizeof(LNode) );
	LinkList b2= (LinkList) malloc(sizeof(LNode) );
	A->next=a1;a1->next=a2;a2->next=a3;a3->next=NULL;
	a1->data=2;a2->data=3;a3->data=5;
	B->next=b1;b1->next=b2;b2->next=NULL;
	b1->data=2;b2->data=3;
	LinkList p=A->next,q=B->next;
	printf("A中元素:");
	while(p){
		printf("%d ",p->data);p=p->next;
	} printf("\nB中元素:");
	while(q){
		printf("%d ",q->data);q=q->next;
	}printf("\n执行取交集操作之后:\n");
	GetCommon(A,B);
	p=A->next,q=B->next;
	printf("A中元素:");
	while(p){
		printf("%d ",p->data);p=p->next;
	} printf("\nB中元素:");
	while(q){
		printf("%d ",q->data);q=q->next;
	}
}
第五题:

问题描述:编写函数,用非递归算法,求二叉链表表示的二叉树T的高度要求写出算法思想以及相应代码:
代码

//2013数据结构第五题 
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{
	int data;
	struct BTNode* l;
	struct BTNode* r;
}BTNode,*BiTree;
int BTDepth(BiTree T){
	if(!T){return 0;}
	BiTree Q[maxsize],p;
	int front=-1,rear=-1;
	int last=0,level=0;//一层中最后一个节点,level表示已经访问的层数 
	Q[++rear]=T;//根节点入队,开始处理
	while(front<rear)
	{
		p=Q[++front];
		if(p->l){Q[++rear]=p->l;}
		if(p->r){Q[++rear]=p->r;}
		if(last==front)//如果访问到某层的最后一个节点 
		{
			level++;
			last=rear; 
		}
	} 
	return level;
}
int main()
{
	//自己定义一些二叉树试一试 
	BiTree r= (BiTree)malloc(sizeof(BTNode));
	r->l=NULL;r->r=NULL;
	printf("该树有%d层\n",BTDepth(r));
	
	BiTree a21= (BiTree)malloc(sizeof(BTNode));
	a21->l=NULL;a21->r=NULL;
	r->l=a21;
	printf("该树有%d层\n",BTDepth(r));
	
	BiTree a31= (BiTree)malloc(sizeof(BTNode));
	BiTree a32= (BiTree)malloc(sizeof(BTNode));
	a21->l=a31;a21->r=a32;
	a31->l=NULL;a31->r=NULL;a32->l=NULL;a32->r=NULL;
	printf("该树有%d层\n",BTDepth(r));
	//其他情况自己去试吧 
}

2014年真题

第四题

问题描述:设带头结点的单链表L,数据元素为(a1,a2,a3,a4,…,an),编写函数调整该链表,要求是的元素顺序为(a1,a3,…,an,…,a4,a2),要求T(n)=n,给出算法思想并写出相关代码
代码

//2014数据结构第四题 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;

void fun(LinkList A){
	LinkList p = A->next;
	if(!p->next){return;}
	LinkList q = p->next; /* p 指向 A 的第一个结点 */
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	B->next = NULL; /* 创建链表 B */
	while (p&&q)
	{
		p->next = q->next;
		q->next = B->next;
		B->next = q;
		if(p->next){
			p=p->next;
			q=p->next;
		}else{break;}
	}
	p->next = B->next; /* A 后接 B */
	free(B);
}
int main()
{
	LinkList a= (LinkList) malloc(sizeof(LNode) );
	LinkList b= (LinkList) malloc(sizeof(LNode) );
	LinkList c= (LinkList) malloc(sizeof(LNode) );
	LinkList d= (LinkList) malloc(sizeof(LNode) );
	LinkList e= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a->data=11;
	b->data=22;
	c->data=33;
	d->data=44;
	e->data=55;
	A->next=a;
	a->next=b;
	b->next=c;
	c->next=d;
	d->next=e;
	e->next=NULL;
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}printf("\n");
	fun(A);
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}
}
第五题

问题描述:设有一家谱树,用二叉链表结构存储(孩子兄弟表示法),树的节点信息为成员名字,编写函数,输出家谱中共有多少代以及最后一代人的人数以及成员名字,要求先给出代码再写出相应代码。
代码

//2014数据结构第五题 
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{//和13年有所不同 
	int data;
	struct BTNode* l;//现在l是孩子  
	struct BTNode* r;//现在r是兄弟 
}BTNode,*BiTree;
void BTDepth(BiTree T){
	if(!T){return;}
	BiTree Q[maxsize],p;
	int front=-1,rear=-1,top=-1;
	int last=0,level=0,count=1;
	Q[++rear]=T;//根节点入队,开始处理
	while(front<rear)
	{	p=Q[++front];//出队、访问 
		++top;//入栈、保存 (逻辑栈)
		if(p->l!=NULL){
			p=p->l;Q[++rear]=p;//有孩子就把孩子入队 
			while(p->r!=NULL)
			{p=p->r;Q[++rear]=p;}} //其他孩子也入队 
		if(last==front)//如果访问到某层的最后一个节点 
		{	level++;
			last=rear; 
			if(rear>front){
				count=last-front;//如果这不是最后一层,就更新一下即将出队的下一层的人数 
			} 
		}
	} 
	printf("最后一代%d个人,共有%d代\n",count,level);
	while(count>0){
		printf("%d ",Q[top--]->data);
		count--;
	}printf("\n");
}
int main()
{
	BiTree root=   (BiTree)malloc(sizeof(BTNode));
	BiTree r11= (BiTree)malloc(sizeof(BTNode));
	BiTree r12= (BiTree)malloc(sizeof(BTNode));
	BiTree r13= (BiTree)malloc(sizeof(BTNode));
	BiTree r14= (BiTree)malloc(sizeof(BTNode));
	root->data=100;
	root->l=NULL;root->r=NULL;
	BTDepth(root);
	
	root->l=r11;root->r=NULL;
	r11->data=101;
	r11->l=NULL;r11->r=NULL;
	BTDepth(root);
	
	r11->r=r12;
	r12->data=102;
	r12->l=NULL;r12->r=NULL;
	BTDepth(root);
	
	r12->r=r13;
	r13->data=103;
	r13->l=NULL;r13->r=NULL;
	BTDepth(root);
	
	r13->l=r14;
	r14->data=104;
	r14->l=NULL;r14->r=NULL;
	BTDepth(root);
}

2015年真题

第四题

问题描述:设有一个带头结点的单链表L,数据元素为整数,编写函数,通过调整该链表中的节点指针,对链表进行简单选择排序(元素值从小到大),先给出算法思想,然后写出相应代码。
代码

//2015数据结构第四题 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;

void ListSort(LinkList A){
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	B->next=NULL;
	LinkList pre=A,maxpre=A,p=A->next,max=A->next;
	while(A->next)
	{
		pre=A;maxpre=A;p=A->next;max=A->next;
		while(p){
			if(p->data>max->data){
				maxpre=pre;max=p;
			}
			pre=pre->next;
			p=p->next;
		}
		maxpre->next=max->next;
		max->next=B->next;
		B->next=max; 
	}
	A->next=B->next;
	free(B);
}
int main()
{
	LinkList a= (LinkList) malloc(sizeof(LNode) );
	LinkList b= (LinkList) malloc(sizeof(LNode) );
	LinkList c= (LinkList) malloc(sizeof(LNode) );
	LinkList d= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a->data=4;
	b->data=3;
	c->data=5;
	d->data=2;
	A->next=a;
	a->next=b;
	b->next=c;
	c->next=d;
	d->next=NULL;
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}printf("\n");
	ListSort(A);
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}

}
第五题

问题描述:设二叉树T,用二叉链表结构存储(孩子兄弟表示法),编写函数,输出最长的一枝(根到叶子)的所有节点,先给出算法思想,然后写出相应代码。
代码

//2015DS第五题
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{//和13年有所不同 
	int data;
	struct BTNode* l;//现在l是孩子  
	struct BTNode* r;//现在r是兄弟 
}BTNode,*BiTree;
void postTravel(BiTree T)
{
	BiTree S[maxsize],Q[maxsize],p=T,r=NULL;//栈用于后序非递归访问二叉树 
	int top=-1,front=-1,rear=-1;//队列用于存储最长路径(持续更新) 
	while(p||top>-1)
	{
		while(p){//走到最左边 
			S[++top]=p;
			p=p->l;
		}
		if(!p){
			p=S[top];
			if(p->r&&p->r!=r)//如果有右子树且未被访问 
			{
				p=p->r;
				S[++top]=p;
				p=p->l;
				 
			}
			else{//如果没有右子树、或者右子树已经被访问:弹出 
				p=S[top--];
				if(!p->l&&!p->r)// 如果该节点是叶子 
				{//并且这条路径是当前最长的 
					if(top+2>rear-front)//这里原本有个小bug被改过来了:top应该+2表示当前栈中元素 
					{//更新路径 
						int t=-1;
						rear=-1;
						while(t<=top){
							Q[++rear]=S[++t];
						}
					}
				}
		 		r=p;p=NULL;
			}
		}
	}
	while(front<rear){//打印一下 
		printf("%d  ",Q[++front]->data);
	}printf("\n");
} 
int main()
{
	BiTree root=(BiTree)malloc(sizeof(BTNode));
	BiTree r1= (BiTree)malloc(sizeof(BTNode));
	BiTree r2= (BiTree)malloc(sizeof(BTNode));
	BiTree r3= (BiTree)malloc(sizeof(BTNode));
	BiTree r4= (BiTree)malloc(sizeof(BTNode));
	root->data=100;r1->data=101;r2->data=102;r3->data=103;r4->data=104;
	root->l=r1;root->r=NULL;
	r1->l=NULL;r1->r=NULL;
	postTravel(root);
	
	r1->r=r2;
	r2->l=NULL;r2->r=NULL;
	postTravel(root);
	
	root->r=r3;
	r3->l=NULL;r3->r=NULL;
	postTravel(root);
	
	root->r=NULL;
	r1->l=r3;
	postTravel(root);
	
	r2->l=r4;
	r4->l=NULL;r4->r=NULL;
	postTravel(root);
}

2016年真题

第四题

问题描述:设L为带头结点的单链表,元素值为整数,编写函数,删除L中的重复节点(具有相同元素值的节点只保留一个),先给出算法思想,然后写出程序代码。
代码

//2016数据结构第四题 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;
void del(LinkList L)
{
	LinkList p=L->next,q=NULL,pre=NULL;
	if(!p){return;} 
	while(p){
		//对于每个节点p,都要将链表里的每个节点遍历一遍确保无重复 
		pre=p;q=p->next;//pre保存q的前驱 
		while(q)
		{
			if(p->data==q->data)
			{	//摘下q,free掉 
				pre->next=q->next;
				free(q);
				q=pre->next;
			}
			else{
				pre=pre->next;
				q=q->next;
			}
		}
		p=p->next;
	}
}
int main()
{
	LinkList a= (LinkList) malloc(sizeof(LNode) );
	LinkList b= (LinkList) malloc(sizeof(LNode) );
	LinkList c= (LinkList) malloc(sizeof(LNode) );
	LinkList d= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a->data=11;
	b->data=22;
	c->data=11;
	d->data=33;
	A->next=a;
	a->next=b;
	b->next=c;
	c->next=d;
	d->next=NULL;
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}printf("\n");
	del(A);
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}
}
第五题

问题描述:已知一棵二叉链表表示的二叉树T,编写函数,判断T是否是完全二叉树,先给出算法思想,然后给出相关程序代码。
代码

//2016数据结构第五题 
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{
	int data;
	struct BTNode* l;
	struct BTNode* r;
}BTNode,*BiTree;
bool check(BiTree T){
	if(!T){return false;}
	BiTree Q[maxsize],p;
	int front=-1,rear=-1;
	Q[++rear]=T;//根节点入队,开始处理
	while(front<rear)
	{
		p=Q[++front];
		if(p->l&&p->r)//左右均不空,先入队 
		{
			Q[++rear]=p->l;
			Q[++rear]=p->r;
		}
		else if(p->r&&!p->l)
		{//左空右不空,必非完全二叉树 
			return false;
		}
		else{//左不空有空或者左右均空,则必须确保其后面的所有节点都是叶子节点,否则非完全二叉树 
			if(p->l&&!p->r){
				Q[++rear]=p->l;
			}
			while(front<rear)
			{
				p=Q[++front];
				if(p->r||p->l)
				{//找到非叶子节点 
					return false;
				}
			}
		}
	} return true;
}
void check_p(BiTree T)
{
	if(check(T)){
		printf("该树为完全二叉树\n");
	}else{
		printf("非完全二叉树\n");
	}
}
int main()
{
	BiTree root=(BiTree)malloc(sizeof(BTNode));
	BiTree r1= (BiTree)malloc(sizeof(BTNode));
	BiTree r2= (BiTree)malloc(sizeof(BTNode));
	BiTree r3= (BiTree)malloc(sizeof(BTNode));
	BiTree r4= (BiTree)malloc(sizeof(BTNode));
	root->data=100;r1->data=101;r2->data=102;r3->data=103;r4->data=104;
	root->l=NULL;root->r=NULL;
	check_p(root);
	
	r1->l=NULL;r1->r=NULL;
	root->l=r1;
	check_p(root);
	
	r2->l=NULL;r2->r=NULL;
	root->r=r2;
	check_p(root);
	
	r3->l=NULL;r3->r=NULL;
	r2->l=r3;
	check_p(root);
	
	r4->l=NULL;r4->r=NULL;
	r1->l=r4;
	check_p(root);
	
	r1->r=r3;r2->l=NULL;
	check_p(root);
	
}

2017年真题

第四题

问题描述:设A、B为递减有序(元素值为整型)的单链表,编写函数,利用原节点将他们合并成为一个递增有序的单链表,相同元素值只保留一个节点,先给出算法思想再给出相应代码。
代码

//2017数据结构第四题 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;
LinkList Merge(LinkList A,LinkList B)
{
	LinkList p=A->next,q=B->next,s=NULL;
	LinkList C=(LinkList)malloc(sizeof(LNode));
	C->next=NULL;
	while(p&&q){
		if(p->data==q->data)
		{
			s=p;
			p=p->next;
			s->next=C->next;
			C->next=s;
			s=q;
			q=q->next;
			free(s);
		}
		else{
		 if(p->data>q->data)
			{
				s=p;p=p->next;
			}
		else{
				s=q;q=q->next;
			}
			s->next=C->next;
			C->next=s;
		} 
	}
	while(p){
		s=p;p=p->next;
		s->next=C->next;
		C->next=s;
	}
	while(q){
		s=q;q=q->next;
		s->next=C->next;
		C->next=s;
	}
	return C;
}
int main()
{
	LinkList a1= (LinkList) malloc(sizeof(LNode) );
	LinkList b1= (LinkList) malloc(sizeof(LNode) );
	LinkList c1= (LinkList) malloc(sizeof(LNode) );
	LinkList d1= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a1->data=4;//递减有序 
	b1->data=3;
	c1->data=2;
	d1->data=1;
	A->next=a1;
	a1->next=b1;
	b1->next=c1;
	c1->next=d1;
	d1->next=NULL;
	
	LinkList a2= (LinkList) malloc(sizeof(LNode) );
	LinkList b2= (LinkList) malloc(sizeof(LNode) );
	LinkList c2= (LinkList) malloc(sizeof(LNode) );
	LinkList d2= (LinkList) malloc(sizeof(LNode) );
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	a2->data=9;//递减有序 
	b2->data=5;
	c2->data=3;
	d2->data=1;
	B->next=a2;
	a2->next=b2;
	b2->next=c2;
	c2->next=d2;
	d2->next=NULL;
	
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	for(LinkList p=B->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	
	LinkList p=Merge(A,B);
	for(p=p->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
}
第五题

问题描述:设有n个学生成绩(0-100整数)的顺序结构线性表L,编写函数,将该线性表调整为成绩及格(大于等于60)在不及格之前,要求T(n)=O(n),S(n)=O(1),先给出算法思想,然后给出相应代码。
代码

//2017数据结构第五题 
#include<stdio.h>
void judge(int* a,int n)
{
	//主体思路是这样的,两个指针分别从首尾向中间遍历,
	//首指针遇到及格的就后移,遇到不及格的就将不及格的放到尾处并将原本的尾元素置换回来 
	//直到两指针相遇结束。时间复杂度O(n),空间复杂度O(1) 
	int i=0,j=n-1;
	while(i<j){
		if(a[i]>=60){i++;}
		else{
			int temp=a[i];
			a[i]=a[j];
			a[j]=temp;
			j--;
		}
	}
} 
int main()
{
	int a[6]={41,99,62,38,70,55};
	for(int i=0;i<6;i++)
	{
		printf("%d\t",a[i]);
	}printf("\n");
	judge(a,6);
	for(int i=0;i<6;i++)
	{
		printf("%d\t",a[i]);
	}printf("\n");
}

2018年真题

第四题

问题描述:设一个带头结点的单链表L,数据元素为整数,其中大部分为正数,少数为负数,要求编写函数,采用尽可能高效的算法调整链表,实现将负数节点转移到链表尾部,并返回调整后链表中的第一个负数节点位置。先给出算法思想,再给出相应代码。
代码

//2018数据结构第四题
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;
LinkList func(LinkList L)
{
	if(!L){return NULL;}
	LinkList A=(LinkList)malloc(sizeof(LNode));
	LinkList pre=L,p=L->next,rear=A;
	while(p)
	{
		if(p->data<0)
		{
			pre->next=p->next;
			rear->next=p;
			rear=p;
			p=pre->next;
		}
		else{
			pre=pre->next;
			p=p->next;
		}
	}
	rear->next=NULL;
	pre->next=A->next;
	free(A);
	return pre->next;
} 
int main()
{
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	LinkList a= (LinkList) malloc(sizeof(LNode) );
	LinkList b= (LinkList) malloc(sizeof(LNode) );
	LinkList c= (LinkList) malloc(sizeof(LNode) );
	LinkList d= (LinkList) malloc(sizeof(LNode) );
	A->next=a;a->next=b;b->next=c;c->next=d;d->next=NULL;
	a->data=5;b->data=-3;c->data=6;d->data=-4;
	printf("A中元素:");
	LinkList p=A->next;
	while(p){
		printf("%d\t",p->data);p=p->next;
	}printf("\n");
	
	func(A);
	printf("A中元素:");
	p=A->next;
	while(p){
		printf("%d\t",p->data);p=p->next;
	}printf("\n");
}
第五题

问题描述:设二叉树T,用二叉链表结构存储,元素值为整数且互不相同,编写非递归函数,对给定的2个整数,如两个都不是T的元素,输出-2,如1个都不是T的元素,输出-1,如都是T的元素,输出两者所在层数的间隔数,先给出算法思想,再给出相应代码。
代码

//2018数据结构第五题 
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{
	int data;
	struct BTNode* l;
	struct BTNode* r;
}BTNode,*BiTree;
int function(BiTree T,int x,int y)
{
	if(!T)return -2;
	int level=0,level1=-1,level2=-1;
	int last=0,front=-1,rear=-1;
	BiTree Q[maxsize],p;
	Q[++rear]=T;
	while(front<rear)
	{
		p=Q[++front];
		if(p->l){
			Q[++rear]=p->l;
		}
		if(p->r){
			Q[++rear]=p->r;
		}

		if(p->data==x){
			level1=level;
		}
		if(p->data==y){
			level2=level;
		}
		if(last==front)
		{
			level++;last=rear;
		}
	}
	if(level1==level2&&level1==-1)
	{
		return -2;
	}
	if(level1==-1||level2==-1)
	{
		return -1;
	}
	else return level2>level1?level2-level1:level1-level2;
}
int main()
{
	BiTree root=(BiTree)malloc(sizeof(BTNode));
	BiTree r1= (BiTree)malloc(sizeof(BTNode));
	BiTree r2= (BiTree)malloc(sizeof(BTNode));
	BiTree r3= (BiTree)malloc(sizeof(BTNode));
	BiTree r4= (BiTree)malloc(sizeof(BTNode));
	root->data=100;r1->data=101;r2->data=102;r3->data=103;r4->data=104;
	root->l=r1;root->r=r2;
	r1->l=r3;r1->r=NULL;
	r2->l=NULL;r2->r=r4;
	r3->l=NULL;r3->r=NULL;
	r4->l=NULL;r4->r=NULL;
	int a=100,b=101;
	printf("%d与%d在树上的层次间隔为:%d\n",a,b,function(root,a,b));
	
	a=100,b=5;
	printf("%d与%d在树上的层次间隔为:%d\n",a,b,function(root,a,b));
	
	a=103,b=104;
	printf("%d与%d在树上的层次间隔为:%d\n",a,b,function(root,a,b));
	
	a=103,b=100;
	printf("%d与%d在树上的层次间隔为:%d\n",a,b,function(root,a,b));
	
	a=10,b=5;
	printf("%d与%d在树上的层次间隔为:%d\n",a,b,function(root,a,b));
}

2019年真题

第四题

问题描述:设A、B为递减有序(元素值为整型)的单链表,编写函数,利用原节点将他们合并成为一个递增有序的单链表,相同元素值只保留一个节点,先给出算法思想再给出相应代码。
代码

//2017数据结构第四题 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;
LinkList Merge(LinkList A,LinkList B)
{
	LinkList p=A->next,q=B->next,s=NULL;
	LinkList C=(LinkList)malloc(sizeof(LNode));
	C->next=NULL;
	while(p&&q){
		if(p->data==q->data)
		{
			s=p;
			p=p->next;
			s->next=C->next;
			C->next=s;
			s=q;
			q=q->next;
			free(s);
		}
		else{
		 if(p->data>q->data)
			{
				s=p;p=p->next;
			}
		else{
				s=q;q=q->next;
			}
			s->next=C->next;
			C->next=s;
		} 
	}
	while(p){
		s=p;p=p->next;
		s->next=C->next;
		C->next=s;
	}
	while(q){
		s=q;q=q->next;
		s->next=C->next;
		C->next=s;
	}
	return C;
}
int main()
{
	LinkList a1= (LinkList) malloc(sizeof(LNode) );
	LinkList b1= (LinkList) malloc(sizeof(LNode) );
	LinkList c1= (LinkList) malloc(sizeof(LNode) );
	LinkList d1= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a1->data=4;//递减有序 
	b1->data=3;
	c1->data=2;
	d1->data=1;
	A->next=a1;
	a1->next=b1;
	b1->next=c1;
	c1->next=d1;
	d1->next=NULL;
	
	LinkList a2= (LinkList) malloc(sizeof(LNode) );
	LinkList b2= (LinkList) malloc(sizeof(LNode) );
	LinkList c2= (LinkList) malloc(sizeof(LNode) );
	LinkList d2= (LinkList) malloc(sizeof(LNode) );
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	a2->data=9;//递减有序 
	b2->data=5;
	c2->data=3;
	d2->data=1;
	B->next=a2;
	a2->next=b2;
	b2->next=c2;
	c2->next=d2;
	d2->next=NULL;
	
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	for(LinkList p=B->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	
	LinkList p=Merge(A,B);
	for(p=p->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
}
第五题

问题描述:求二叉树的宽度,给出算法思想以及使用到的数据结构。
代码

//2019数据结构第五题   求宽度 
#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{
	int data;
	struct BTNode* l;
	struct BTNode* r;
}BTNode,*BiTree;
int BTDepth(BiTree T){
	if(!T){return 0;}
	BiTree Q[maxsize],p;
	int front=-1,rear=-1,width=1;
	int last=0;//一层中最后一个节点
	Q[++rear]=T;//根节点入队,开始处理
	while(front<rear)
	{
		p=Q[++front];
		if(p->l){Q[++rear]=p->l;}
		if(p->r){Q[++rear]=p->r;}
		if(last==front)//如果访问到某层的最后一个节点 
		{
			if(rear-front>width){
				width=rear-front;
			}
			last=rear; 
		}
	} 
	return width;
}
int main()
{
	//自己定义一些二叉树试一试 
	BiTree r= (BiTree)malloc(sizeof(BTNode));
	r->l=NULL;r->r=NULL;
	printf("该树宽%d\n",BTDepth(r));
	
	BiTree a21= (BiTree)malloc(sizeof(BTNode));
	a21->l=NULL;a21->r=NULL;
	r->l=a21;
	printf("该树宽%d\n",BTDepth(r));
	
	BiTree a31= (BiTree)malloc(sizeof(BTNode));
	BiTree a32= (BiTree)malloc(sizeof(BTNode));
	a21->l=a31;a21->r=a32;
	a31->l=NULL;a31->r=NULL;a32->l=NULL;a32->r=NULL;
	printf("该树宽%d\n",BTDepth(r));
	//其他情况自己去试吧 
}

2020年真题

第四题

问题描述:设单链表L的元素都是整数,编写一个高效函数,查找链表的中位节点并删除该节点,先给出算法思想然后写出相应代码。
代码

#include<stdio.h> 
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;
bool deleteMid(LinkList L){
	if(!L||!L->next){
		return false;
	}
	LNode *slow=L,*fast=L->next->next,*p=NULL;
	while(fast&&fast->next){
		slow=slow->next;
		fast=fast->next->next;
	}
	p=slow->next;
	slow->next=slow->next->next;
	free(p);
	return true;
}
int main(){
	LinkList a= (LinkList) malloc(sizeof(LNode) );
	LinkList b= (LinkList) malloc(sizeof(LNode) );
	LinkList c= (LinkList) malloc(sizeof(LNode) );
	LinkList d= (LinkList) malloc(sizeof(LNode) );
	LinkList e= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a->data=11;
	b->data=22;
	c->data=33;
	d->data=44;
	e->data=55;
	A->next=a;
	a->next=b;
	b->next=c;
	c->next=d;
	d->next=NULL;
	//e->next=NULL;
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}printf("\n");
	deleteMid(A);
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d ",p->data);
	}
}
第五题

问题描述:设一棵树,用孩子兄弟二叉链表表示,编写函数,给定树中的节点p,求p的双亲节点,给出算法思想以及相应代码。
代码

#include <malloc.h>
#include <stdio.h>
#define maxsize 50
typedef struct BTNode {
  int data;
  struct BTNode* l;  //现在l是孩子
  struct BTNode* r;  //现在r是兄弟
} BTNode, *BiTree;
BiTree BTLevel(BiTree T, BiTree target) {  // target是给出的待求节点
  if (!T || T == target) {
    return NULL;
  }  //如果target是根节点、或者树为空,就结束
  BiTree Q[maxsize], p, father = NULL;  // father用于标记
  int front = -1, rear = -1;
  Q[++rear] = T;  //根节点入队,开始处理
  while (front < rear) {
    p = Q[++front];  //出队、访问
    father = p;      //暂存一下可能的father
    if (p->l != NULL) {
      p = p->l;
      Q[++rear] = p;  //有孩子就把孩子入队
      if (p == target) {
        return father;
      }
      while (p->r != NULL) {
        p = p->r;
        Q[++rear] = p;
        if (p == target) {
          return father;
        }
      }
    }  //其他孩子也入队
  }
  return NULL;
}
int main() {
  BiTree root = (BiTree)malloc(sizeof(BTNode));
  BiTree r1 = (BiTree)malloc(sizeof(BTNode));
  BiTree r2 = (BiTree)malloc(sizeof(BTNode));
  BiTree r3 = (BiTree)malloc(sizeof(BTNode));
  BiTree r4 = (BiTree)malloc(sizeof(BTNode));
  root->data = 100;
  r1->data = 101;
  r2->data = 102;
  r3->data = 103;
  r4->data = 104;
  root->l = r1;
  root->r = NULL;
  r1->l = r3;
  r1->r = r2;
  r2->l = r4;
  r2->r = NULL;
  r3->l = NULL;
  r3->r = NULL;
  r4->l = NULL;
  r4->r = NULL;
  BiTree fa = BTLevel(root, r2);
  if (!fa) {
    printf("未找到!\n");
  } else {
    printf("\n%d\n", fa->data);
  }

2021年真题

第一题

问题描述:孩子兄弟链表中指定节点p,要求得到其孩子、兄弟以及双亲节点。
代码

#include<stdio.h> 
#include<malloc.h>
#define maxsize 50
typedef struct BTNode{
	int data;
	struct BTNode* l;//现在l是孩子  
	struct BTNode* r;//现在r是兄弟 
}BTNode,*BiTree;
BiTree findFather(BiTree T,BiTree target){
	//层次遍历求target的父亲 
	if(!T||T==target){return NULL;}//如果target是根节点、或者树为空
	BiTree Q[maxsize],p,father=NULL;//father用于标记 
	int front=-1,rear=-1;
	Q[++rear]=T;//根节点入队,开始处理
	while(front<rear)
	{	p=Q[++front];//出队、访问 
		father=p; //暂存一下可能的father 
		if(p->l!=NULL){//第一个孩子入队
			p=p->l;Q[++rear]=p; 
			if(p==target){return father;}
			while(p->r!=NULL)
			{	//其他孩子也入队 
				p=p->r;Q[++rear]=p;
				if(p==target){return father;}
			}
		} 
	} 
	return NULL;
}
void findBro(BiTree father,BiTree target){
	//输出所有兄弟 
	printf("\ntarget的所有兄弟:"); 
	for(BiTree p=father->l;p!=NULL;p=p->r){
		if(p!=target){
			printf("%d ",p->data);
		}
	}
}
void findSon(BiTree target){
	//输出所有孩子 
	printf("\ntarget的所有孩子:"); 
	for(BiTree p=target->l;p!=NULL;p=p->r){
		printf("%d ",p->data);
	}
}
void findF_B_S(BiTree root,BiTree target){
	if(root==NULL)return;
	if(root==target){
		printf("未找到父结点和兄弟节点\n");
		findSon(target);
		return;
	}
	BiTree f=findFather(root,target);
	if(!f){printf("未找到父结点、兄弟节点和孩子节点\n"); return;}
	printf("\n%d\n",f->data);
	findBro(f,target);
	findSon(target);
}
int main()
{
	BiTree root=(BiTree)malloc(sizeof(BTNode));
	BiTree r1= (BiTree)malloc(sizeof(BTNode));
	BiTree r2= (BiTree)malloc(sizeof(BTNode));
	BiTree r3= (BiTree)malloc(sizeof(BTNode));
	BiTree r4= (BiTree)malloc(sizeof(BTNode));
	root->data=100;
	r1->data=101;
	r2->data=102;
	r3->data=103;
	r4->data=104;
	root->l=r1;
	root->r=NULL;
	r1->l=r3;
	r1->r=r2;
	r2->l=r4;
	r2->r=NULL;
	r3->l=NULL;
	r3->r=NULL;
	r4->l=NULL;
	r4->r=NULL;
	findF_B_S(root,r2);
}
第四题

问题描述:a链表递增,b链表递减,合并链表,要求相同节点保留一个,合并之后链表递增。
代码

//2021数据结构第四题 
// a链表递增 b链表递减 合并他们 相同节点保留一个 合并之后链表递增
// 思路:这一题和19年第四题类似,可以采取先将a链表原地逆置,后再将两个递减的链表归并的做法
// 可以算出时间复杂度为O(m+n) 
#include<stdio.h>
#include<malloc.h>
typedef struct LNode{
	int data;
    LNode *next;
} *LinkList,LNode;

LinkList Reverse(LinkList A){
	//本方法对链表A进行原地倒转 
	LinkList p=A->next;
	A->next=NULL;
	while(p!=NULL){
		LinkList q=p->next;
		p->next=A->next;
		A->next=p;
		p=q; 
	}
}
void Merge(LinkList A,LinkList B){
	//本方法将AB两个递减有序的链表合并为递增有序;结果保存在A中 
	LinkList p=A->next,q=B->next,s=NULL;//从AB两链表的首个元素开始遍历
	A->next=NULL;
	while(p&&q){
		if(p->data==q->data)
		{
			//把p头插法插入A链表 
			s=p->next;
			p->next=A->next;
			A->next=p;
			p=s;
			//删除q(因为重复) 
			s=q;
			q=q->next;
			free(s);
		}
		else{
		 	if(p->data>q->data){s=p;p=p->next;}
			else{s=q;q=q->next;}
			s->next=A->next;
			A->next=s;
		} 
	}
	//尾处理:考虑一个链表遍历完之后,剩余另一个链表未遍历 
	while(p){
		s=p;p=p->next;
		s->next=A->next;
		A->next=s;
	}
	while(q){
		s=q;q=q->next;
		s->next=A->next;
		A->next=s;
	}
}
void fun(LinkList A,LinkList B){
	Reverse(A);
	Merge(A,B);
}
int main()
{
	LinkList a1= (LinkList) malloc(sizeof(LNode) );
	LinkList b1= (LinkList) malloc(sizeof(LNode) );
	LinkList c1= (LinkList) malloc(sizeof(LNode) );
	LinkList d1= (LinkList) malloc(sizeof(LNode) );
	LinkList A= (LinkList) malloc(sizeof(LNode) );
	a1->data=1;//递减有序 
	b1->data=2;
	c1->data=3;
	d1->data=4;
	A->next=a1;
	a1->next=b1;
	b1->next=c1;
	c1->next=d1;
	d1->next=NULL;
	
	LinkList a2= (LinkList) malloc(sizeof(LNode) );
	LinkList b2= (LinkList) malloc(sizeof(LNode) );
	LinkList c2= (LinkList) malloc(sizeof(LNode) );
	LinkList d2= (LinkList) malloc(sizeof(LNode) );
	LinkList B= (LinkList) malloc(sizeof(LNode) );
	a2->data=9;//递减有序 
	b2->data=5;
	c2->data=3;
	d2->data=1;
	B->next=a2;
	a2->next=b2;
	b2->next=c2;
	c2->next=d2;
	d2->next=NULL;
	
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	for(LinkList p=B->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
	fun(A,B);
	for(LinkList p=A->next;p!=NULL;p=p->next)
	{
		printf("%d\t",p->data);
	}printf("\n");
}
第五题

问题描述:小顶堆编程,把a[i]的数值改为val,并重新调整成为小顶堆,要求算法的时间复杂度为log2n。
代码

#include<stdio.h>
#include<malloc.h>
void swap(int* arr, int i, int j) {
    int temp=arr[i];arr[i]=arr[j];arr[j]=temp;
}
void heapify(int* arr, int i,int len) {//小顶化 
    int left=i*2+1,right=i*2+2;//左右孩子
    int minIndex=i;//找出最小的孩子 
    if (left<len && arr[left]<arr[minIndex]){
        minIndex=left;//如果左孩子最小
    }
    if (right<len && arr[right]<arr[minIndex]){
        minIndex=right;//如果右孩子最小
    }
    if (minIndex != i){//父亲节点比孩子大->不满足小顶堆->调整
        //交换之后,父节点变成最小的了
        swap(arr,minIndex,i);
        //但是被交换的孩子此刻不一定符合小顶堆 
        heapify(arr,minIndex,len);//递归地heapify
		//形象地理解为让大值继续往下沉淀直到沉不下去
    }
}
void buildMaxHeap(int* arr,int len) {//建堆
    for (int i=(len-2)/2;i>=0;i--){
		//从最后一个非叶节点一直调整到根节点为止
        heapify(arr,i,len);
    }
}
void heapSort(int* arr,int len){
    buildMaxHeap(arr,len);//建堆
    for (int i=len-1;i>0;i--){
        //输出对顶元素,把堆顶最小值放到堆末,堆顶变成一个较大值 
        swap(arr,0,i);
        len--;
        //调整堆:从新的对顶元素开始调整
        heapify(arr,0,len);
    }
}
void adjust(int* arr,int len,int index,int val){
	//先讲arr[index]修改为val
	arr[index]=val;
	//再重新调整为小顶堆 
	for(int i=index;i>=0;i=(i-1)/2){
		heapify(arr,i,len);
		//如果父节点更小,则停止对父节点的调整 
		if(i==0||arr[i]>arr[(i-1)/2])break;
	}
}
int main(){
	int arr[]={1,3,5,7,9,2,4,6,8,10};
	for(int i=0;i<10;i++){printf("%d ",arr[i]);}printf("\n");
	buildMaxHeap(arr,10);//建堆
	for(int i=0;i<10;i++){printf("%d ",arr[i]);}printf("\n");
	adjust(arr,10,4,2);
	for(int i=0;i<10;i++){printf("%d ",arr[i]);}printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌空暗羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值