一、编程题目
(1)输入某班级学生的姓名、分数,并对分数进行降幂排列并输出;
#include <iostream> using namespace std; struct Node { char name[100]; int score; Node *next; }; void show(Node *head) { while(head) { cout<<head->name<<" "<<head->score<<endl; head = head->next; } } int linkLen(Node *head) { int len = 0; while(head) { len++; head = head->next; } return len; } void sort(Node *head) { int len = linkLen(head); for(int j=len-1; j>0; j--) { Node *tempHead = head; for(int i=0; i<j; i++) { if(tempHead->score> tempHead->next->score) { char tempName[100]; int tempScore; strcpy(tempName,tempHead->next->name); strcpy(tempHead->next->name, tempHead->name); strcpy(tempHead->name, tempName); tempScore = tempHead->next->score; tempHead->next->score = tempHead->score; tempHead->score = tempScore; } } } } int main() { char name[100]; int score; Node *head = NULL; Node *tail = NULL; scanf("%s %d", name, &score); while(score != -1) { Node *temp = new Node; strcpy(temp->name, name); temp->score = score; temp->next = NULL; if(head == NULL) { head = temp; tail = temp; } else { tail->next = temp; tail = temp; } scanf("%s %d", name, &score); } show(head); sort(head); show(head); return 0; }
(2)随即产生一字符串,每次产生的字符串内容、长度都不同;
#include <iostream> using namespace std; int main() { //可见字符的范围为32~126 srand(time(0)); int len = rand()%1000; char *a = new char[len+1]; for(int i=0; i<len; i++) { a[i] = char(rand()%95 + 32); } a[len] = '\0'; cout<<a<<endl; return 0; }
(3)可输入二进制、八进制、十进制、十六进制数;将已输入的数转换成其余进制的数;
#include <iostream> using namespace std; void show(int num_dec, int m)//num_dec为十进制的数字,m为几进制,例如二进制m为2, 八进制m为8 { if(num_dec>1) { show(num_dec/m, m); printf(" "); } printf("%x", num_dec%m); } int toDec(int num, int m)//把一个m进制的数(这个数是用10进制表示的)转化成十进制的数 { int k = 1; int dec = 0; while(num) { dec += (num%m)*k; k *= m; num /= 10; } return dec; } void showAll(int num_dec, int m) { if(m != 2) { printf("二进制为:\n"); show(num_dec, 2); printf("\n"); } if(m != 8) { printf("八进制为:\n"); show(num_dec, 8); printf("\n"); } if(m != 10) { printf("十进制进制为:\n"); show(num_dec, 10); printf("\n"); } if(m != 16) { printf("十六进制进制为:\n"); show(num_dec, 16); printf("\n"); } } int main() { int m; int num; int num_dec; printf("请输入进制数:\n"); scanf("%d", &m); printf("请输入该进制的数值;\n"); scanf("%d", &num); num_dec = toDec(num, m); showAll(num_dec, m); return 0; }
(4)输入数字,以-1为标识结束,结果保存在a.txt中
#include <iostream> using namespace std; int main() { FILE *fp = fopen("a.txt", "a+"); if(fp == NULL) return -1; char buffer[100] = {0}; while(fgets(buffer, 100, stdin)) { if(strcmp(buffer, "-1\n") == 0) break; fputs(buffer, fp); } return 0; }
(5)给一个字符串,找出其中连续重复出现且最长的子串,例如“ababc“要求返回“ab”。请用C/C++语言写一函数完成该算法。
#include <iostream> using namespace std; int common(char *str1, char *str2) { int common = 0; while(*str1 != '\0' && *str2 != '\0' && *str1 == *str2) { str1++; str2++; common++; } return common; } void comStr(char *str, char *result) { int len = strlen(str); int maxLen = 0; char *com= NULL; for(int i=0; i<len; i++) { char *temp = &str[i]; int tempLen = strlen(temp); for(int j=1; j<=tempLen/2; j++) { if(common(temp, &temp[j]) == j) { if(j > maxLen) { maxLen = j; com = temp; } } } } strncpy(result, com, maxLen); } int main() { char str[] = "aabcabc"; char result[100] = {0}; comStr(str, result); cout<<result<<endl; return 0; }
(6)设X[1..n]和Y[1..n]为两个数组每个都包含n个已排好序的数。请使用伪代码给出一个求数组X和Y中所有2n个元素的中位数的O(lgn)时间的算法。
O(lgn)时间肯定是2分了。分析:
数组X有n个元素,数组Y有n个元素,且都是从小到大排好的。那么找中位数是找第(2n+1)/2个元素是哪个。
一共有2n的元素,取各自数组中间的一个第(n-1)/2个元素,设为Xmid和Ymid(下标为0到n-1),那么在
1)n为奇数的时候,对于数组X和数组Y有(n-1)/2个元素在第Xmid和Ymid之前,现在假设
a.Xmid>Ymid 这个时候如果两个数组有序的排好后,会有至少(n-1)/2*2+1(这个1为Ymid) = n个元素在Xmid之前也就是说,这个待寻找的中位数也在Xmid之前,也就是说这个中位数不可能在X数组Xmid元素之后,所以可以排除一半X数组中的元素。而且最多会有(n-1)/2*2 = n-1个元素在Ymid之前,所以这个中位数肯定不会比Ymid小,所以不会出现在Y数组Ymid之前,排除一半Y中的元素(同理Xmid<Ymid的时候也是这样分析)
b.Xmid = Ymid这个就比较好了,中位数就是Xmid了。
2)n为偶数的时候,也取Xmid =X[(n-1)/2]
a.Xmid>Ymid,这个时候各自有(n-2)/2个元素在Xmid和Ymid元素之前,那么如果这两个数组排序,会有至少(n-2)/2*2+1=n-1个元素在Xmid之前,如果为偶数那么中位数为第(2n+1)/2=n个元素,这个时候Xmid至少为第n个元素,所以这个中位数也不可能出现在Xmid这个元素之后。至多会有n-2个元素在Ymid之前,所以中位数肯定在Ymid之后。同样排除了一半的X和Y中的元素。
代码如下:但是写的有问题,在n为奇数的时候正确,在偶数的时候就不对了。二分对于边界的判断有点烦啊,时间问题,以后修改
#include <iostream> using namespace std; int middle(int *a1, int s1, int e1, int *a2, int s2, int e2) { if(s2 == e2) return a2[s2]; if(s1 == e1) return a1[s1]; int a1_mid = a1[(e1+s1)/2]; int a2_mid = a2[(e2+s2)/2]; if(a1_mid == a2_mid) return a1_mid; else if(a1_mid > a2_mid) return middle(a1, s1, (e1+s1)/2, a2, (e2+s2)/2, e2); else return middle(a1, (e1+s1)/2, e1, a2, s2, (e2+s2)/2); } int main() { int a1[] = {1, 3, 5, 7, 9}; int a2[] = {2, 4, 6, 8, 10}; cout<<middle(a1, 0, 4, a2, 0, 4)<<endl; return 0; }
二、其他部分
(1)winsock建立连接的主要实现步骤?
服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。
客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv(),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。
服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesocket()关闭套接字。
(2)动态连接库的两种方式?
调用一个DLL中的函数有两种方法:
1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向系统提供了载入DLL时所需的信息及DLL函数定位。
2.运行时动态链接(run-time dynamic linking),运行时可以先载入DLL,DLL载入后,模块在获取DLL函数的地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了。
(3)曹操南下攻打刘备,刘备派关羽守锦州,关羽派张飞去守城门。刘备又派诸葛亮去向孙权求援。孙权派兵攻打曹操! 请画出UML图(这个一开始没看懂,以为要画类图什么的,看了网上一个人给的图才知道,这个最适合话交互图的顺序图了)参考如下: