题目列表
函数题
01-复杂度3 二分查找
代码
Position BinarySearch( List L,ElementType X){
int min = 1, max = L->Last;
int M, res, flag = 0;
for(; min <= max; ){
M = (min + max) / 2;
if( X == L->Data[M]){
res = M;
flag = 1;
break;
}else if( X < L->Data[M]){
max = M-1;
}else if( X > L->Data[M]){
min = M+1;
}
}
if (flag == 0)
res = NotFound;
//return NotFound;
return res;
}
总结&纠错
错误:
1.未理解参数X含义引用;
2.循环内未改变M;
3.原:max=M,min=M;
现:max=M-1,min=M+1;————>运行用时减少;
4.大错误!!flag == 0 写成了 flag = 0
02-线性结构1 两个有序链表序列的合并 (15 分)
代码
List Merge( List L1, List L2 ){
List pa,pb,p,s;
/*if(L1->Next == NULL && L2->Next ==NULL ){
return NULL;
}*/
p = (List)malloc(sizeof(struct Node));
s = p;
pa = L1->Next;
pb = L2->Next;
/*while( pa && pb ){
switch(compare( pa->Data, pb->Data)){
case 1:
s->Next = pa;
//s = s->Next;
s = pa;
pa = pa->Next;
break;
case -1:
s->Next = pb;
//s = s->Next;
s = pb;
pb = pb->Next;
break;
case 0:
s->Next = pa;
//s = s->Next;
s = pa;
pa = pa->Next;
break;
}
}*/
while( pa && pb){
if(pa->Data <= pb->Data){
s->Next = pa;
//s = s->Next;
s = pa;
pa = pa->Next;
}else{
s->Next = pb;
s = pb;
pb = pb->Next;
}
}
/*while(L1 ){
s->Next = L1;
}
while(L2 ){
s->Next = L2;
}*/
s->Next = pa?pa:pb;
L1->Next = NULL;
L2->Next = NULL;
return p;
}
编程题
01-复杂度1 最大子列和问题 (20 分)
代码
//算法1、2、3、4的程序代码
#include<stdio.h>
#include<math.h>
int readnum(int *A,int n);
int MaxSubseqSum1(int A[],int N);
int MaxSubseqSum2(int A[],int N);
int Max3( int A, int B, int C );
int DivideAndConquer( int List[], int left, int right);
int MaxSubseqSum3( int List[], int N );//保持与前两种算法同样的接口——算法3
int MaxSubseqSum4( int List[], int N );//保持与前两种算法同样的接口——算法4
int main(){
int Max_num;
int res;
scanf("%d",&Max_num);
int A[Max_num+1];
if(readnum(A,Max_num) == 0)
res = 0;
else{
res = MaxSubseqSum4(A,Max_num);
}
printf("%d",res);
return 0;
}
int readnum(int *A, int n){
int flag = 0;
for(int i=0; i<n; i++){
scanf("%d",&A[i]);
if(A[i] >= 0) flag = 1;
}
return flag;
}
/*算法1————O(n^3)*/
int MaxSubseqSum1( int A[],int N){
int ThisSum,MaxSum = 0;
int i,j,k;
for( i = 0; i < N; i++){
for( j = i; j < N; j++){
ThisSum = 0;
for( k = i; k <= j; k++){
ThisSum += A[k];
}
if( ThisSum > MaxSum){
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
/*算法2————O(n^2)*/
int MaxSubseqSum2( int A[],int N){
int ThisSum,MaxSum = 0;
int i,j;
for( i = 0; i < N; i++){ /*i是子列左端位置*/
ThisSum = 0; /*ThisSum是从A[i]到A[j]的子列和*/
for( j = i; j < N; j++){/*j是子列右端位置*/
ThisSum += A[j];
/*对于相同的i,不同的j,只要在j-1次循环的基础上累加1项即可*/
if( ThisSum > MaxSum){/*如果刚得到的这个子列和更大*/
MaxSum = ThisSum;/*则更新结果*/
}
}/*j循环结束*/
}/*i循环结束*/
return MaxSum;
}
int Max3( int A, int B, int C )
{ /* 返回3个整数中的最大值 */
return A > B ? A > C ? A : C : B > C ? B : C;
}
int DivideAndConquer( int List[], int left, int right )
{ /* 分治法求List[left]到List[right]的最大子列和 */
int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */
int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界线的结果*/
int LeftBorderSum, RightBorderSum;
int center, i;
if( left == right ) { /* 递归的终止条件,子列只有1个数字 */
if( List[left] > 0 ) return List[left];
else return 0;
}
/* 下面是"分"的过程 */
center = ( left + right ) / 2; /* 找到中分点 */
/* 递归求得两边子列的最大和 */
MaxLeftSum = DivideAndConquer( List, left, center );
MaxRightSum = DivideAndConquer( List, center+1, right );
/* 下面求跨分界线的最大子列和 */
MaxLeftBorderSum = 0; LeftBorderSum = 0;
for( i=center; i>=left; i-- ) { /* 从中线向左扫描 */
LeftBorderSum += List[i];
if( LeftBorderSum > MaxLeftBorderSum )
MaxLeftBorderSum = LeftBorderSum;
} /* 左边扫描结束 */
MaxRightBorderSum = 0; RightBorderSum = 0;
for( i=center+1; i<=right; i++ ) { /* 从中线向右扫描 */
RightBorderSum += List[i];
if( RightBorderSum > MaxRightBorderSum )
MaxRightBorderSum = RightBorderSum;
} /* 右边扫描结束 */
/* 下面返回"治"的结果 */
return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum );
}
int MaxSubseqSum3( int List[], int N )
{ /* 保持与前2种算法相同的函数接口 */
return DivideAndConquer( List, 0, N-1 );
}
int MaxSubseqSum4( int A[], int N){
int ThisSum, MaxSum;
int i;
ThisSum = MaxSum = 0;
for( i = 0; i < N; i++ ){
ThisSum += A[i];
if( ThisSum > MaxSum )
MaxSum = ThisSum;
else if( ThisSum < 0)
ThisSum = 0;
}
return MaxSum;
}
总结
1.运用四种方法,时间复杂度从大到小,分别是三重循环、二重循环、分治法、在线处理法
2.通过MOOC课程的富文本文档改写,非自己写的。
01-复杂度2 Maximum Subsequence Sum (25 分)
代码
#include<stdio.h>
#include<math.h>
void Readnum( int *A, int K);//读入数组
int Maxsub( int A[], int K, int *head, int *rear);//求最大子列和,返回结构体
int main(){
int K;
int res; //结果
int rhead,rrear;
scanf("%d",&K);
int A[K+1];
int *head = &rhead;
int *rear = &rrear; //结果首尾项
*head = 1;
*rear = K;
Readnum( A, K);
res = Maxsub( A, K, head, rear);
printf("%d %d %d", res, A[*head], A[*rear]);
return 0;
}
void Readnum( int *A, int K){
for(int i=1; i<=K; i++){
scanf("%d",&A[i]);
}
}
int Maxsub( int A[], int K, int *head, int *rear){//求最大子列和
int ThisSum,Maxsum;
int i;
int h,r;
ThisSum = Maxsum = 0;
h = 1;
for( i = 1; i <= K; i++ ){
ThisSum += A[i];
if( ThisSum > Maxsum ){
Maxsum = ThisSum;
*rear = i;
*head = h;
}
else if( ThisSum < 0){
ThisSum = 0;
h = i+1;
}
else if( A[i]==0 & ThisSum == 0 & Maxsum == 0){
*head = i;
*rear = i;
}
}
return Maxsum;
}
总结
1.关于指针的定义与初始化需额外加强;
2.数组给出负数和0,应找出零及其所在下标
02-线性结构2 一元多项式的乘法与加法运算 (20 分)
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//未完待续
typedef int ElementType;
typedef struct Node *n;
struct Node{
ElementType coef;
ElementType expon;
n next;
};
typedef n list;
list Read(); //读入数字
list Multiple(list L1, list L2); //多项式乘积结果
list Sum(list L1, list L2); //多项式和结果
void Print(list L); //打印多项式
void Attach(int c, int e, n *p); //尾插法
int Compare(int a, int b); //比较数大
int main(){
list L1,L2;
list mul,sum;
L1 = Read();
L2 = Read();
mul = Multiple(L1, L2);
sum = Sum( L1, L2);
Print(mul);
Print(sum);
return 0;
}
//尾插法函数!
void Attach(int c, int e, n *p){
list L = (list)malloc(sizeof(struct Node));
L->next = NULL;
L->coef = c;
L->expon = e;
(*p)->next = L;
*p = L;
}
/*
总结:
函数内用*p(指针的指针)应该用括号!
如(*P)->next
尾插法不需要删除临时结点(即无临时结点)
1.新建节点L,L->next 为空
2.数据赋给新节点L
3.*p(指针的指针)(尾结点指针的指针)
新节点L 赋给*p(尾结点)的next节点——使链表连接
4.新节点L 赋给*P(尾结点)代表新的尾结点
*/
list Read(){
list p,s,t;//p是最后返回值,s是操作链
int i;
scanf("%d",&i);
p = (list)malloc(sizeof(struct Node));//申请头结点
p->next = NULL; //头指针为空
s = p;
while(i--){
int c, e;
scanf("%d %d", &c, &e);
Attach(c,e,&s);
}
t = p;
p = p->next;
free(t);
return p;
}
/*
疑问:
1.为什么list r = (list)malloc(sizeof(Node));
中间直接填Node不行?而是要 Struct Node?
*/
/*
总结:
运用尾插法进行读入操作
1.新建节点P,此节点P作为临时表头(临时空节点)
Note:赋值节点P next为空(指链表结束符
2.将P赋给尾结点rear(防止丢失表头&紧跟表头插入元素
3.N 需插入节点数
当n不为0,读入节点数据,用Attach尾插插入元素
n--
4.删除临时生成的头结点
list t;
t = P; P = P->link; free(t);
return P;
Tips:
1.while 和 i-- 同时需要时,可直接写作while(i--)
*/
list Multiple(list L1, list L2){
list p,s;
list a,b;
int c,e;
if(!L1 || !L2) return NULL;
a = L1;
b = L2;
p = (list)malloc(sizeof(struct Node));
p->next = NULL;
s = p;//s表示尾结点
while(b){ /*先用L1的第1项乘以L2,得到P*/
Attach((a->coef * b->coef),(a->expon + b->expon),&s);
b = b->next;
}
a = a->next;//L1的第二项
while(a){//现在s链表中已经有上述的循环产生的链表了
b = L2;
s = p;
while(b){
c = a->coef * b->coef;//新节点的系数
e = a->expon + b->expon;//新节点的指数
/*判断s下一节点是否不为空 &&
s下一节点的指数是否大于新节点的指数*/
while(s->next && s->next->expon > e){
s = s->next; //s指向下一节点
}
/*下一节点指数相等*/
if(s->next && s->next->expon == e){
//要考虑系数相加是否为0的情况
if(s->next->coef + c){
s->next->coef += c;
}else{//链表下一节点的删除操作!
list t;
t = s->next;
s->next = t->next;
free(t);
}
}
else if(c){/*下一节点指数小于新节点指数 或 下一节点空*/
list t = (list)malloc(sizeof(struct Node));
t->coef = c;
t->expon = e;
/*插入操作*/
t->next = s->next;
s->next = t;
s = s->next;
}
b = b->next;
}
a = a->next;
}
//删头结点
b = p;
p = p->next;
free(b);
return p;
}
/*
总结:
1.记得判空
2.原理:先用链表1的第一项循环乘链表2的每一项,
形成新链表p,然后再用表1乘表2的每一项判断插入
3.用malloc函数新建为表头头结点空节点
在最后应视情况删节点
纠错
4.应为b = b->next, 错写为a = a->next.
5.与4错有关,ab和所代表的L1、L2弄错了
6.e = a->expon + b->expon;//新节点的指数
错写为
e = a->expon + b->coef;//新节点的指数
7.c = a->coef * b->coef;//新节点的系数
错写为
c = a->coef + b->coef;//新节点的系数
*/
list Sum(list L1, list L2){
list p,s;//p返回值,s操作值
list a,b;//a——L1,b——L2
p = (list)malloc(sizeof(struct Node));
p->next = NULL;
s = p;
if(!L1 && !L2){
return NULL;
}
a = L1;
b = L2;
while(a && b){
switch( Compare( a->expon, b->expon)){
case 1:
Attach(a->coef,a->expon,&s);
a = a->next;
break;
case 0:
if(a->coef + b->coef){
Attach(a->coef+b->coef,a->expon,&s);
}
a = a->next;
b = b->next;
break;
case -1:
Attach(b->coef,b->expon,&s);
b = b->next;
break;
}
}
while(a){
Attach(a->coef, a->expon, &s);
a = a->next;
}
while(b){
Attach(b->coef, b->expon, &s);
}
list t;
t = p;
p = p->next;
free(t);
return p;
}
/*
纠错:
1.while(a)里应有a = a->next;(未加)
*/
void Print(list L){
if(!L){
printf("0 0");
return;
}
printf("%d %d", L->coef, L->expon);
L = L->next;
while(L){
printf(" %d %d", L->coef, L->expon);
L = L->next;
}
printf("\n");
return;
}
/*
纠错:
1.printf("%d %d",&L->coef,&L->expon);
会把L的地址打印出来,而不是打印需要的数字
*/
int Compare(int a, int b){
int flag;
if( a > b){
flag = 1;
}else if( a == b){
flag = 0;
}else {
flag = -1;
}
return flag;
}
/*
纠错:
1.else if(a == b) 错写为else if(a = b)
*/
总结
1.第一次自己写链表,好不容易写到几乎都正确了,只是最后一个样例“输入有零多项式和常数多项式”的结果是内存超限,不知道该怎么纠错,其他错点均在代码中每个函数下指出
03-树1 树的同构 (25 分)
代码
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define MaxTree 10
#define ElementType char
#define Tree int
#define Null -1
struct TreeNode
{
ElementType Element;
Tree Left;
Tree right;
}T1[MaxTree],T2[MaxTree]; //T1,T2已经在这里定义,视为全局变量
Tree BuildTree(struct TreeNode T[]);
int Isomorphic(Tree R1, Tree R2);
int main(){
Tree R1,R2;
R1 = BuildTree(T1);
R2 = BuildTree(T2);
if(Isomorphic(R1, R2)){
printf("Yes");
}else{
printf("No");
}
return 0;
}
Tree BuildTree(struct TreeNode T[]){
int N;
int root = Null;
int i;
char cl, cr;
scanf("%d\n",&N); //重要改错节点!!
int check[N];
if(N){
for( i=0; i<N; i++){ //初始化check数组
check[i] = 0;
}
for( i=0; i<N; i++){ //读取树的数值,左右
scanf("%c %c %c\n", &T[i].Element, &cl, &cr);
if(cl != '-'){ //判断是否为空,存入数字,check判断
T[i].Left = cl - '0';
check[T[i].Left] = 1;
}else{
T[i].Left = Null;
}
if(cr != '-'){
T[i].right = cr - '0';
check[T[i].right] = 1;
}else{
T[i].right = Null;
}
}
for( i=0; i<N; i++){
if(check[i] == 0){
root = i;
break;
}
}
}
return root;
}
/*
纠错:
1.T[i].element/left/right 错写为 T.element/left/right
2.int check[N] 未出错
3.cl,cr应定义为char 错定义为int
4.scanf("%d\n",&N);
写为 scanf("%d",&N); 时,仅两个样例正确,错误大多为段错误
改正后仅一个样例错误
*/
int Isomorphic(Tree R1, Tree R2){
if((R1 == Null) && (R2 == Null)){
return 1;
}else if(((R1 == Null) && (R2 != Null)) || ((R1 != Null) && (R2 == Null))){
return 0;
}else if( T1[R1].Element != T2[R2].Element){
return 0;
}else if((T1[R1].Left == Null) && (T2[R2].Left == Null)){
return ( Isomorphic( T1[R1].right, T2[R2].right));
}else if( ((T1[R1].Left != Null) && (T2[R2].Left != Null))
&& ((T1[T1[R1].Left].Element) == (T2[T2[R2].Left].Element))){
//* no need to swap the left and the right
return( Isomorphic( T1[R1].Left, T2[R2].Left)
&& Isomorphic( T1[R1].right, T2[R2].right) );
}else{ //* need to swap the left and the right
return( Isomorphic( T1[R1].Left, T2[R2].right)
&& Isomorphic( T1[R1].right, T2[R2].Left));
}
}
/*
纠错:
1.T1[R1].Element != T2[R2].Element 错写为 R1 != R2
*/