厦大数据结构2010年903 程序设计题 1.(15分)试用C语言编写一个遍历二叉查找树的算法,要求遍历过程刚好按照键值从大到小的次序进行. 解: 二叉查找树(BST:Binary Search Tree)是一种特殊的二叉树,它改善了二叉树节点查找的效率。 二叉查找树有如下性质: (1)若左子树不空,则左子树上全部节点的值均小于它的根节点的值 (2)若右子树不空,则右子树上全部节点的值均大于它的根节点的值 (3)左、右子树也分别为二叉排序树 (4)没有键值相等的节点 所以,有如下数据结构定义: typedef struct BSTreeNode{ //数据域 ElemType data; //递归定义 左右子树 struct BSTreeNode *left; struct BSTreeNode *right; }BSTree; void BSTreeSearch(tree *t){ if (t == NULL) { return ; } else { BSTreeSearch(t->rchild); visit(t); BSTreeSearch(t->lchild); } } 2.(15分)设L是一个带头结点的非递减有序单链表的表头指针. 试设计一个算法,将元素e插入到链表L中的合适地方,使得该链表还是非递减有序. 解: 单链表的数据结构声明: typedef struct LinkList{ ElemType data; LinkList *next; }*L; void insert(list &L, element a){ L = L -> next; while (a > L -> data && a <= L-> next -> data){ L = L -> next; } Node* newNode; newNode -> data = a; newNode -> next = L -> next; L -> next = newNode; } //插入新结点 void insert(LinkList * newNode){ LinkList *temp = L; while (temp -> next != NULL) { if (temp -> next -> num > newNode -> num){ break; } temp = temp -> next; } newNode -> next = temp -> next; temp -> next = newNode; } //打印列表 void output() { LinkList *p; p = L -> next; while (p != NULL){ printf("%d\t", p->num); } printf("\n"); } int main(){ L = new LinkList; L -> next = NULL; L -> num = MAXN; int n; while(1){ scanf("%d",&n); LinkList *now; now = new LinkList; now -> next = NULL; insert(now); output(); } return 0; } //--------------------------------------------------------------// 厦大数据结构2011年903 程序设计题 1.(15分)有一个带头结点的单链表L = {a1,b1a2,b2,...,an,bn}. 请设计一个函数将其拆分为两个带头结点的单链表A和B,正序链表A= {a1,a2,..,an}, 逆序链表B={bn,bn-1,...,b2,b1}.要求链表A使用链表L的头结点. [注]函数的头部为void split(LinkList *&L, LinkList *&A, LinkList *&B) 解: typedef struct LinkList{ ElemType data; LinkList *next; }*L; //头插法拆分链表 void split(LinkList *&L, LinkList *&A, LinkList *&B){ LinkList *p,*q; A = p = q = L; while (p -> next != NULL){ q = p -> next -> next; p -> next -> next = q -> next; //弹出最近的B,插入到B链表的头结点后 q -> next = B -> next; B -> next = q; p = p -> next -> next; } } LinkList splitLinkList(LinkList &A){ LinkList B = (LinkList) malloc (sizeof(NODE)); B -> next = NULL; //p为工做指针 LinkList p = A -> next,q; LinkList ra = A; while (p){ ra -> next = p; ra = p; //q是为了防止断链 q = p -> next; p -> next = B -> next; B -> next = p; p = q; } ra -> next = NULL; return B; } 2.(15分)假设用单链表方式来存储整数序列,以下形式: [0| ] -> [3| ] -> [0| ] -> [3| ] -> [1| ] -> [3| ^] 请编写一个递归算法,对这样的链表进行处理,重复结点(值相同的结点). 仅保留排在最前面的一个,最后返回新链表的首地址. 例如,如有上述链表,则处理后的新链表以下: [0| ] -> [3| ] -> [1|^] 解: 算法思想:从单链表的第一个结点开始,对每一个结点进行检查: 检查链表中该结点的全部后继结点,只要有值和该结点的值相同,则删除值; 而后检查下一个结点,知道全部的结点都被检查完. typedef struct LNode { ElemType data; struct LNode *next; } //递归删除以L为头结点的单链表中全部值相同的结点 void RecDelete_Node(LNode *L){ if (L == NULL) return; LNode *pre = L; LNode *cur = pre -> next; while (cur!=NULL){ if (cur->data == L->data){ pre -> next = cur -> next; free(cur); cur = pre -> next; } else { pre = cur; cur = cur -> next; } } L = L -> next; RecDelete_Node(L); } //非递归算法 void IterDeleteNode(LNode *L){ //删除以单链表L中全部值相同的结点 LNode *p = L,*q,*ptr; //删除以单链表L中全部值相同的结点 while (p != NULL) { q = p, ptr = p -> next; //检测结点p的全部后继结点ptr while (ptr != NULL) { if (ptr -> data = p -> data) { q -> next = ptr -> next; free(ptr); ptr = q -> next; } else { q = ptr; ptr = ptr -> next; } } p = p -> next; } } //--------------------------------------------------------------// 厦大数据结构2012年903 程序设计题 1.(15分)在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表, 请设计算法去掉数值相同的元素,使表中再也不有重复的元素. 例如,下列线性表(7,10,10,21,30,42,42,42,61,70) 将变成(7,10,21,30,42,51,70) 请分析所设计算法的时间复杂度. 解: 数据结构定义: typedef struct LinkList{ ElemType data; LinkList *next; }*L; LinkList DeleteSameElem(LinkList &L){ //表按照增序排列(从小到大),去掉相同元素,使得表中再也不有相同元素 LNode *pre = L; LNode *p = L -> next; LNode *s = L; while (p != NULL) { if (pre -> data == p -> data){ //防止断链 s = p; pre -> next = p -> next; p = p -> next; //释放相同元素结点空间 free(s); } else { //若不相等时,同时后移 p = p -> next; pre = pre -> next; } } return L; } (2006年期末考卷A卷) 2.(15分)试设计算法在O(n)时间内将数组A[0..n-1]划分为左右两个部分,使得左边的元素均为 奇数,右边的元素均为偶数,要求所使用的辅助空间大小为O(1). 解: 主要思路: (1)设置两个指针i和j,其中i=1,j = n; (2)当i < j时,做以下循环: i不断自增 从左往右 找到第一个偶数 j不断自减 从左往右 找到第一个奇数 A[i]和A[j],不断交换 (3)算法结束 void Adjust (int a[], int n){ int i = 0; int j = n -1; while (a[i]%2 != 0){ i++ } while (a[j]%j == 0){ j++ } if (i < j){ int temp = a[i]; a[i] = a[j]; a[j] = temp; } } int main(){ int a[6] = {1,3,2,4,8,6}; Adjust(a,6); for (int i = 0; i < 6; i++){ printf("%5d\n",a[i]); } return 0; } //--------------------------------------------------------------// 厦大数据结构2013年903 程序设计题 1.(15分)请利用两个队列Q1和Q2来模拟一个栈. 已知队列的三个运算,定义以下: bool EnQueue(Queue &Q, int e):插入一个元素e入队列 bool DeQueue(Queue &Q, int &e):删除一个元素e出队列 bool QueueEmpty(Queue Q):判队列为空 假设数据结构Queue已定义,栈Stack的数据结构定义以下: typedef struct{ Queue Q1; Queue Q2; }Stack; 请利用队列的运算来实现该栈的三个运算: Push(ST,x):元素x入ST栈 Pop(ST,x):ST栈顶元素出栈,赋给变量x StackEmpty(ST):判ST栈是否为空 void Push(Stack ST,element x) { element e; //把Q1中全部元素压入Q2 while (!QueueEmpty(ST.Q1)){ //删除Q1中准备被压入Q2的元素 DeQueue(ST.Q1,e); //把Q2取出来的元素压入Q1队列 EnQueue(ST.Q2,e); } EnQueue(ST.Q1,x); while (!QueueEmpty(ST.Q2)) { //删除Q2中准备被压入Q1的元素 DeQueue(ST.Q2,e); //把Q2取出来的元素压入Q1队列 EnQueue(ST.Q1,e); } } //用队列模拟出栈比入栈容易的多,因为刚刚压入的元素在队列Q1的头, //只要弹出即为弹栈操做 void Pop(Stack ST,element){ element e; //队列为空,没法完成弹栈 if (QueueEmpty(ST.Q1)) return; DeQueue(ST.Q1,e); } bool StackEmpty(Stack ST){ if (QueueEmpy()){ return true; } else { false; } } 2.(15分)下面小题与二叉树的遍历有关系: (1)已知二叉树的后序序列"abcdefg",同时已知二叉树的中序序列"acbgdef", 是否能惟一肯定一棵二叉树?若是能,请画出二叉树 (2)假设post[ps..ps+n-1]为二叉树的后序序列,ins[is..is+n-1]为二叉树的中序序列. 设计算法由两个序列构造二叉树的二叉链表. 解:(1)图略 (2)程序以下: BTNode *CreateBT(char *post, char *in, char *n) { BTNode *s; char *p; if (n <= 0) return NULL; s = (BTNode*)malloc(sizeof(NTNode)); s -> data = *(post+(n-1)); for (p = in; p < in+n; p++) { if (*p == *(post+(n-1))) break; k = p - in; s -> lchild = CreateBT(post,in,k); s -> rchild = CreateBT(post,p+1,n-k-1); } return s; } Status CreateBiTree(BiTree &T) { scanf(&ch); if (ch == NULL) T = NULL; else { if ((!T=(BiTree*)malloc(sizeof(BiTNode)))) exit(OVERFLOW); T -> data = ch; CreateBiTree(T -> lchild); CreateBiTree(T -> rchild); } return OK; } //--------------------------------------------------------------// 厦大数据结构2014年903 程序设计题 1.(15分)判断两个非递减有序的线性表中是否存在相同(关键字值相等)的元素, 若是相同的元素,返回第一个相同的元素在第一个有序表中的位置,不然返回0. 请合适的物理存储结构,用C语言给出该物理存储结构的类型定义,并在其上编写算法. typedef struct{ ElemType *elem; int length; int listsize; }List; int judge(List A, List B){ for (int i = 0; i < A.length; i++){ int flag = 0; for (int j = 0; j < B.length; j++){ if (A.elem[i] == B.elem[j]){ flag = i; break; } } } return flag; } 2.(15分)编写函数判断一棵二叉树是否不含有度为1的结点,若任何结点的度都不为1, 则返回TRUE,不然返回FALSE,结点与二叉树的数据结构以下: typedef struct BiNode(){ TElemType Data; //左右孩子指针 struct BiTNode *lchild,*rchild; } BiTNode,*BiTree; 程序设计以下: int search(BiTNode *tree){ if ((tree -> lchild == NULL && tree -> rchild != NULL) || (tree -> rchild == NULL && tree -> lchild != NULL)){ return false; } else { //判断是叶子节点,什么都不作 if (tree -> lchild == NULL && tree -> rchild == NULL){ } else { search(tree -> lchild); search(tree -> rchild); } //可以到达这一步说明全部节点就没有单个孩子,则返回true; return true; } } //本题采用递归思想,非递归的思想也能实现.可是递归可以反应算法素养,每每能获得更高的分. //--------------------------------------------------------------// 厦大数据结构2015年903 程序设计题 1.(15分)在n个元素中,找到第k大的元素,用C语言写出数据结构,设计算法实现上述要求, 并分析时间复杂性,最好是平均时间复杂度为O(n). 解: 思路:寻找n个数中最大的k个数,本质上就是寻找最大的k个数中最小的那个,也就是第k大的数. 可使用二分搜索的策略来寻n个数中的第k大的数. 用数组a[max]做为存储数据结构,在数组a中查找. 算法代码以下: //快速排序的划分函数 int partition(int a[], int l, int r){ int i,j,x,temp; i = l; j = r + 1; x = a[l]; //将>=x的元素换到左边区域 //将<=x的元素换到右边区域 while (1) { while (a[++i] > x); while (a[--j] < x); if (i >= j) break; temp = a[i]; a[i] = a[j]; a[j] = temp; } a[l] = a[j]; a[j] = x; return j; } //随机划分函数 int random_partition(int a[], int l,int r){ //生产随机数 int i = l + rand()%(r-l+1); a[i] = a[l]; a[l] = temp; //调用划分函数 return partition(a,l,r); } //线性寻找第 k 大的数 int random_select(int a[],int l,int r,int k){ int i,j; if (l == r) //递归结束{ return a[l]; } i = random_partition(a,l,r);//划分 j = i-l+1; if(k == j) //递归结束,找到第 K 大的数 return a[i]; if(k < j) { //递归调用,在前面部分查找第k大的数 return random_select(a,l,i-1,k); } else //递归调用,在后面部分查找第k大的数 return random_select(a,i+1,r,k-j); } 2.(15分)请用C语言写出二叉树的数据结构,并设计判断两个二叉树是否相同(包括二叉树的结构 以及每一个对应的结点的数据域data均相同)的算法. 解: 二叉树的数据结构: typedef struct bitree{ int data; bitree *lchild; bitree *rchild; }bitree; int judgebitree(bitree *bt1, bitree *bt2){ if (bt1 == 0 && bt2 == 0) return (1); else if (bt1 == 0 || bt2 == 0 || bt1 -> data != bt2 -> data){ return (0); } else { return (judgebitree(bt1 -> lchild, bt2 -> lchild) && judgebitree(bt1 -> rchild, bt2 -> rchild)) } } //--------------------------------------------------------------// (排列组合算法) 厦大数据结构2016年903 程序设计题 设计算法以求解从集合{1…n}中选取k(k<=n)个元素的全部组合。例如,从集合{1…4}中选取2个元素的全部组合的输出结果为:1 2,1 3,1 4,2 3, 2 4,3 4。 1.(15分)设计算法以求解从集合{1,n}中来选取k(k<=n)个元素的全部组合. 例如{1,4}中选取2个元素的全部组合的输出结构为1 2,1 3,1 4,2 3,2 4,3 4, 输入:4 2 输出: 1 2 1 3 1 4 2 3 2 4 3 4 函数的头部为Void print_combination(int n, int k) void print_combination(int n, int k){ a[k] = {1,2,3,4}; if (n == k){ for (int i = 0; i < k; i++){ printf("%d\n",a[i]); printf("%d\n"); } } else { for (int j = n; j < k; j++){ print_combination(n+1,k); swap(&a[j], &a[index]); } } } void swap(int *p1, int *p2){ int t = *p1; *p1 = *p2; *p2 = t; } 2.(15分)在彻底二叉树上,给定结点x,按照层次序打印结点x的全部子孙,请给出结点的数据结构和 算法,而且分析算法的时间复杂度. //--------------------------------------------------------------// 厦大数据结构2017年903 程序设计题 1.(15分)写出一个结点具备M个指针会的M对的数据结构,并设计一个递归算法计算M叉树的深度. 其中M为常量,设只有一个根节点的树深度为1,空树深度为0,计算尝试函数的输入为节点指针和 M值. 2.一个仅由0,1,2三种数构成的数组A共有N个元素,乱序排列在一块儿. 0,1,2的数量均大于0,但具体的个数未知,请设计一种时间复杂度为O(n)的算法, 将数组排成以下形状,0,01,12,2(即前面都是0,中间都是1,后面都是2) //--------------------------------------------------------------// 厦大数据结构2018年903 程序设计题 1.(15分)描述下面这个算法,并用非递归形式来实现这个算法. Status time (int &sum){ int x; Scanf("%d\n",&x); if (x == 0){ return sum = 1; } else { time(sum); sum *= x; printf("%d\n",&sum); } return OK; } 2.写二叉树数据结构,叶子浮点型. 二叉树中序遍历3+4*5,设计算法实现这一计算过程.