写在开头:941是吉大计算机学硕专业课科目,采取“1+3”的模式,即408考到的四门中《数据结构》必选,《操作系统》、《计算机组成原理》和《计算机网络》中三选一。《数据结构》是计算机专业的重要基础,也是941考试里与他人拉开距离的重要模块。其中,拉分项主要集中在有一定复杂度的算法题上。算法题有两题,答题应遵循“思想、代码及注释”三部分来进行,先给出解题的基本思路,然后选择C、C++或Java语言来实现,并在代码的基础上给出必要的注释。本文内容为自己整理的历年算法题,给出了C语言的基本代码实现,部分内容因没找到原题以及没有继续关注故没有列出。这份资料躺在自己的笔记文档里已经挺久了。在又一年考研之际,萌发出将其开源的想法。对于其中的内容,自己也许有些生疏了。以及其中的解法,未必是最佳的,甚至可能存在错误。欢迎大家补充与指正!最后祝考研学子考试顺利,希望这份资料对你们有所帮助!
2019年
①改造一个双向链表的头结点T,使 right域保持原有的链表次序,left域根据key的大小顺序连接。
//思想:使right域不变,并用p->right!=NULL循环计数元素个数。然后通过循环找最小值,使之链到头结点T之后。
//然后再找剩余数中的最小值,使之链到头结点T之后,直到剩余的数链完。
struct DuLNode{
int data;
struct DuLNode *right,*left;
};
void Left_to_big(struct DuLNode *T){
int i=0;//用以计数元素个数
struct DuLNode *p,*q,*min,*max;
p=T;
q=T;
max=T->right;
while(p->right!=NULL){
//找到元素中最大值
i++;
if(p->right->data>max->data)
max=p->right;
p=p->right;
}
while(i>0){
//进行i次插入操作
min=max;//max元素为最后一次做left域链入操作
while(q->right!=NULL){
if((q->right->data<min->data)&&(q->right->left==q))//找到剩余元素的最小值,即对应元素的left域没有发生过变化
min=q->right;
q=q->right;
}
q=T;
T=min->left;
min=T->right->left;
i--;
}
}
②一棵n个结点的二叉树的后根遍历序列存放在A数组,中根遍历序列放在B数组,编写算法实现链式二叉树
//思想:根结点在后序遍历A数组中的最后一个元素,在B数组中找到对应根结点的位置,根结点左侧的为左子树元素,右侧为右子树元素。
//然后利用递归的思想,进行建树操作。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef struct node{
char data;
struct node *lchild,*rchild;
}BSTree;
char post[MAXSIZE],ind[MAXSIZE];
int i=0,j=0;
void Postorder(BSTree *p)
{
if(p!=NULL)
{
Preorder(p->lchild);
Preorder(p->rchild);
post[i++]=p->data;
}
}
void Inorder(BSTree *p)
{
if(p!=NULL)
{
Inorder(p->lchild);
ind[j++]=p->data;
Inorder(p->rchild);
}
}
void Post_In_order(char post[],char ind[],int i,int j,int k,int h,BSTree **p)
{
//i、j和k、h分别为当前子树先序序列和中序序列的下、上界
int m;
*p=(BSTree*)malloc(sizeof(BSTree));
(*p)->data=post[i];
m=k;//m指向ind数组所存储的中序序列中的第一个结点
while(ind[m]!=post[i])//找到根结点在中序序列所在的位置
m++;
if(m==k)//根结点是中序序列的第一个结点时则无左子树
(*p)->lchild=NULL;
else
Post_In_order(post,ind,i,i+m-k-1,k,m-1,&(*p)->lchild);//根据根结点所划分出中序序列的两个部分继续构造左、右两棵子树
if(m==h)//根结点是中序序列的最后一个结点时则无右子树
(*p)->rchild=NULL;
else
Post_In_order(post,ind,i+m-k,j-1,m+1,h,&(*p)->rchild);//根据根结点所划分出中序序列的两个部分继续构造左、右两棵子树
}
void Print_Inorder(BSTree *p)
{
if(p!=NULL)
{
Print_Inorder(p->lchild);
printf("%3c",p->data);
Print_Inorder(p->rchild);
}
}
void Createb(BSTree **p)
{
char ch;
scanf("%c",&ch);
if(ch!='.')
{
*p=(BSTree*)malloc(sizeof(BSTree));
(*p)->data=ch;
Createb(&(*p)->lchild);
Createb(&(*p)->rchild);
}
else
*p=NULL;
}
int main()
{
BSTree *root,*root1;
printf("Preorder enter bitree with'..':n");
Createb(&root);
printf("Inorder output root:n");
Print_Inorder(root);
printf("n");
Postorder(root);//先序遍历二叉树生成post数组
printf("Inorder output:n");
Inorder(root);//中序遍历二叉树生成ind数组
if(i>0)//根据数组pred和ind保存的遍历序列恢复二叉树
Post_In_order(post,ind,0,i-1,0,j-1,&root1);
printf("Inorder output root1:n");
Print_Inorder(root1);
printf("n");
return 0;
}
2017年
①(15分)A和B是长度为n的两个数组。设计一个算法,该算法输出长度为n的数组C。要求1:数组C中的每一个元素C[i]=||{A[j]|A[j]<=B[i],1<=j<=n}||,其中||S||表示集合S中的元素个数。例如:下面给出了长度为4的两个数组A和B,以及满足要求的数组C;要求2:所设计算法的时间复杂性低于O(n²)。
i | 1 | 2 | 3 | 4 |
---|---|---|---|---|