老规矩:若针对这些题目,同学们有更好更简洁的方法,欢迎来找助教讨论,助教请喝奶茶😍😍。
连续线段 此题使用链表和数组的解法各有优劣。有些同学在写代码时容易默认输入的点是按x坐标顺序输入的,但其实不然,因此在后续for
循环判断时第一层变量为i
,第二层变量为j = i + 1
,这样就忽略了可能在该线段之前的线段中存在相连的可能性。因此一种实用的做法为先对输入的所有点进行排序,这样在后续判断时也更有逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <stdio.h> #include <stdlib.h> struct node { int x1; int x2; int y1; int y2; }line[201 ]; int cmp (const void * a, const void * b) { struct node * e1 = (struct node *)a; struct node * e2 = (struct node *)b; if (e1->x1 > e2->x1) return 1 ; else if (e1->x1 < e2->x1) return -1 ; else return 0 ; } int main () { int x3=0 , y3=0 ; int i, j, n, count[201 ]={0 }, ans=-1 ; scanf ("%d" , &n); for (i = 0 ; i < n; i++) scanf ("%d %d %d %d" , &line[i].x1, &line[i].y1, &line[i].x2, &line[i].y2); qsort(line, n, sizeof (struct node), cmp); for (i = 0 ; i < n; i++){ x3 = line[i].x2; y3 = line[i].y2; for (j = i + 1 ; j < n; j++){ if (line[j].x1 == x3 && line[j].y1 == y3){ count[i]++; x3=line[j].x2; y3=line[j].y2; } } } j=0 ; for (i=0 ;i<n;i++){ if (count[i]>ans){ ans=count[i]; j=i; } } printf ("%d %d %d\n" , ans+1 , line[j].x1, line[j].y1); return 0 ; }
空闲空间申请模拟(最佳适应) 该题的题面较长,大家一定要看清楚每一个要求,踩坑的地方包括但不限于:
1、找不到足够大的空闲快,则什么操作都不发生;
2、并不是简单地寻找到空间恰好相等的节点,而是遍历一圈找到满足要求的空间最小的节点进行操作;
3、在删除节点时如果使用free()
函数,则一定要保证这个空间后续不会再被使用;
4、一定要注意!不能访问到空指针。形如if(p->length!=0 && p != NULL)
的形式仍是不可以的,因为p
如果是空指针,逻辑上if条件确实不会成立,但仍存在p->length!=0
的判断,这样就访问到了空指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <stdio.h> #include <stdlib.h> struct node { int address; int length; struct node *next ; }dot[512 ]; int main () { int i, j, n, op, min, flag; struct node *p , *q , *r , *r_be , *now ; scanf ("%d" , &n); scanf ("%d %d" , &dot[0 ].address, &dot[0 ].length); for (i = 1 ; i < n; i++){ scanf ("%d %d" , &dot[i].address, &dot[i].length); dot[i-1 ].next = (struct node*)malloc (sizeof (struct node)); dot[i-1 ].next = &dot[i]; } now = dot[n-1 ].next = &dot[0 ]; q = &dot[n-1 ]; while ((scanf ("%d" , &op))!=EOF){ r = (struct node*)malloc (sizeof (struct node)); r_be = (struct node*)malloc (sizeof (struct node)); if (op == -1 ) break ; else { flag = 0 ; p = now; for (q = p; q->next != p; q = q->next); min = 999999 ; do { if (p->length>=op && p->length < min){ r = p; r_be = q; min = p->length; flag = 1 ; } q = p; p = p->next; }while (p != now); if (flag == 1 ){ if (r->length > op){ r->length -= op; now = r; } else if (r->length == op){ r->length = 0 ; if (r->next != r){ now = r->next; r_be->next = r->next; } else { now = NULL ; } } } } } p = now; do { if (p == NULL ) break ; else { printf ("%d %d\n" , p->address, p->length); p = p->next; } }while (p != now); return 0 ; }
多项式相乘 本题需要注意:
1、链表与数组均可解决此问题,各有优劣;
2、注意数据范围,应用long long
存储指数和系数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include <stdio.h> #include <stdlib.h> struct duo { long long xi; long long zhi; }a[81 ], b[81 ], ans[6561 ]; int cmp (const void *a, const void *b) { struct duo * ia = (struct duo*)a; struct duo * ib = (struct duo*)b; if ((ia->zhi < ib->zhi) || ((ia->zhi == ib->zhi) && (ia->xi > ib->xi))) return 1 ; else return -1 ; } int main () { int i=0 , j=0 , k=0 , i1, j1, k1; char c1, c2; while (1 ){ scanf ("%lld %lld" , &a[i].xi, &a[i].zhi); c1 = getchar(); i++; if (c1 == '\n' ) break ; } while (1 ){ scanf ("%lld %lld" , &b[j].xi, &b[j].zhi); c2 = getchar(); j++; if (c2 == '\n' ) break ; } i1 = i; j1 = j; for (i = 0 ; i < i1; i++){ for (j = 0 ; j < j1; j++){ ans[k].xi = a[i].xi * b[j].xi; ans[k].zhi = a[i].zhi + b[j].zhi; k++; } } k1 = k; qsort(ans, k1, sizeof (struct duo), cmp); for (i = 0 ; i < k1; i++){ for (j = 1 ; (j < k1) && (i + j < k1); j++){ if (ans[i+j].zhi == ans[i].zhi){ ans[i].xi += ans[i+j].xi; ans[i+j].zhi = 0 ; } else break ; } } for (i = 0 ; i < k1 - 1 ; i++){ if (ans[i].zhi != 0 ) printf ("%lld %lld " , ans[i].xi, ans[i].zhi); } printf ("%lld %lld " , ans[k1-1 ].xi, ans[k1-1 ].zhi); return 0 ; }
文件加密(环) 该题为本次作业的重重重灾区!问题主要出在:
1、对于输入的字符串没有预处理末尾的换行符,或者处理方式有问题,导致后面全部出错;
2、原密钥对应的最后一个字符的新密钥没有被赋值,导致最终密钥表缺失;
3、对链表的操作不熟悉,对于表头的使用、对于链表节点的插入、删除等操作出现问题;
4、使用野指针或访问空指针,定义局部指针时未初始化。
一些建议:
1、增加对链表的熟悉程度,插入、删除等操作可以自己总结成一个模版;
2、对于复杂的题目,模块化非常重要。自定义好各司其职的函数,main
函数里保留逻辑部分;
3、调试方法与技巧!一定要善于使用printf
函数进行打印调试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 #include <stdio.h> #include <string.h> #include <stdlib.h> struct formation { char c; struct formation *link ; }; void del (char * b, char * c) { int i=0 , j=0 , k=0 ; while (b[i] != '\0' ){ for (j = 0 ; j < k; j++){ if (b[i]==c[j]) break ; } if (j==k) c[k++]=b[i]; i++; } } void sheet (char * b, char * c) { char re[95 ]={0 }; int i, j, k=0 , tmp[95 ]={0 }; del(b,c); j = (int )strlen (c); for (i = 0 ; i < j; i++) tmp[c[i]-' ' ]++; for (i = 0 ; i < 95 ; i++){ if (tmp[i] == 0 ) re[k++] = i + ' ' ; } strcat (c,re); } void final (char * b) { int i, j=0 , k=0 ; struct formation *List = NULL , *p = NULL , *r = NULL ; for (i = 0 ; i < 95 ; i++){ r = (struct formation *)malloc (sizeof (struct formation)); r->c = b[j++]; if (List == NULL ) List = p = r; else { p->link = r; p = p->link; } } p->link = List; r = p; p = p->link; k = p->c; while (p->link != p){ r->link = p->link; j = p->c; free (p); p = (struct formation *)malloc (sizeof (struct formation)); p = r->link; for (i = 1 ; i < j; i++, r=p, p=p->link); b[j-32 ] = p->c; } b[p->c -32 ] = k; } int main () { char s[33 ]={0 }, pre[95 ]={0 }, c; FILE *in = fopen("in.txt" , "r" ); FILE *out = fopen("in_crpyt.txt" , "w" ); gets(s); sheet(s, pre); final(pre); while ((c = fgetc(in)) != EOF){ if (c>=32 && c<=126 ) fputc(pre[c-32 ], out); else fputc(c, out); } fclose(in); fclose(out); return 0 ; }
词频统计(数组或链表实现) 本题使用数组或链表都是可以做的,但个人认为数组会更简洁。需要注意的是,题目中明确说明单词仅为有字母组成的字符序列 ,但并没有说单词与单词之间一定由空格隔开 ,不能只看样例而轻下论断,因此使用fscanf
读取单词肯定是会出问题的。
一些建议:当明确地需要执行排序操作时,数组比链表更为简洁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> struct node { char word[51 ]; int count; }wordlist[512 ]; int cmp (const void * a, const void *b) { struct node *e1 = (struct node*)a; struct node *e2 = (struct node*)b; return strcmp (e1->word,e2->word); } int main () { char table[5120 ]={0 }, c; FILE *in = fopen("article.txt" ,"r" ); int i=0 , j, k, len, total=0 ; while ((c = fgetc(in)) != EOF) table[i++] = c; len = i; for (i = 0 ; i < len;){ if (!isalpha (table[i])) i++; else { j = 0 ; while (isalpha (table[i])){ if (islower (table[i])) wordlist[total].word[j++] = table[i]; else if (isupper (table[i])) wordlist[total].word[j++] = table[i] + 32 ; i++; } wordlist[total].word[j] = '\0' ; wordlist[total].count = 1 ; for (k = 0 ; k < total; k++){ if (strcmp (wordlist[k].word,wordlist[total].word) == 0 ){ wordlist[k].count++; break ; } } if (k == total) total++; } } qsort(wordlist, total, sizeof (struct node), cmp); for (i = 0 ; i < total; i++) printf ("%s %d\n" , wordlist[i].word, wordlist[i].count); fclose(in); return 0 ; }
Author: diandian, Riccardo