详解2021华为笔试三道编程题

 目录

2021华为笔试第一道

缓存转发数据包统计(100%)

解题思路:

参考代码:

2021华为笔试第二题

查找知识图谱中的实例知识(100%)

解题思路:

参考代码:

2021华为笔试第三题

湖泊连通(100%)

解题思路:

参考代码: 


2021华为笔试第一道

缓存转发数据包统计(100%)

题目描述

有k个节点的转发队列,每个节点转发能力为m,缓存能力n(表示此节点可立即转发m个包,剩余的缓存,最多缓存n个包,再剩余的丢弃,缓存的包在下一轮继续转发)。另外,此队列中某些节点可能因故障需要直接跳过转发,但不会有两个连续故障的节点。现分两轮操作,第一轮向此队列发送a个数据包让其转发;第二轮,直接驱动让缓存的数据包继续转发。

求两轮最后可能收到的最少数据包总个数(如果第二轮缓存仍有数据包缓存包按丢弃处理) 1 <= k <= 40 1 <= m,n <= 1000 1 <= a <= 1000

例如:有两个节点,节点1(转发能力m:50,缓存能力n:60) 和节点2(m:30,n:25),发送包数为120。

在没有节点故障时:

图片

输入描述:第一行队列长度k 第二行为k个节点转发能力数组,以空格分隔。m,n以逗号分隔,例如10,20 11,21 12,22 第三行数据包个数a

2
50,60 30,25
120

输出描述:

55 

解释:参见题目中的图例,当第一个节点故障时,仅第二个节点转发,此时收到的包最少。

解题思路:

双层动态规划。

1.首先是定义vector<vector<int>>cap(k+1, vector<int>(2)),保存每个节点的转发能力和缓存能力;(输入节点为第0个节点)

2.定义vector<vector<int>>dp(k+1, vector<int>(2)),保存每个节点第一次转发的数量和第二次转发的数量。(输入节点第一次转发数量为a,第二次转发数量为0)

3.计算(dpfun())每个节点第一次转发和第二次转发的数量send1和send2:

第一次转发的数量为从前一节点接收到的第一次转发的数量和该节点转发能力的最小值:

cur_cap[0]:为当前节点的转发能力,cur_cap[1]:当前节点的缓存能力,也就是dp_fun()传入的cap[i]。

pre[0]:上一节点第一次转发的数量,pre[1]:上一节点第二次转发的数量,也就是dp_fun()传入的cap[i]。

send1 = min(pre[0], cur_cap[0]);

第二次转发的数量需要分情况讨论,即第一次从上一节点转发来的是否全部被转走。不过最大转发数量也就是转发能力与缓存能力加上上一节点第二次转发数量的最小值。

send2 = min(pre[1] + cur_cap[1], cur_cap[0]);

如果上一节点第一次转发的数量大于当前节点的转发能力(有缓存的情况),则当前节点第二次转发的数量为上一节点第二次转发的数量加上当前节点第一次的缓存:

send2 = min(pre[1] + pre[0] - cur_cap[0], send2);

否则,当前节点第二次转发的就是上一节点第二次转发的数量:

send2 = min(pre[1], send2);

4.再分析节点存在故障的情况,因为不会有连续两个节点故障,所以遍历所有节点,交叉转发,然后每一个节点转发情况取较小的一个。

vector<int> res1 = dpfun(dp[i - 1], cap[i]);//前一个节点没有故障
vector<int> res2 = dpfun(dp[i - 2], cap[i]);//前一个节点故障
dp[i] = res1[0] + res1[1] <= res2[0] + res2[1] ? res1 : res2;

5.输出最后一个节点,或倒数第二个节点转发数量中的较小值即可。

res = min(dp[k][0] + dp[k][1], dp[k - 1][0] + dp[k - 1][1]);

参考代码:

#include<bits/stdc++.h>
using namespace std;

//根据前一个节点发送的数据包 和当前节点的能力
//计算当前节点发送的数据包
//pre:前一节点(两次)转发的数量  cur_cap:当前节点(转发能力,缓存能力)
vector<int> dpfun(vector<int> &pre, vector<int> &cur_cap) {
	int send1 = min(pre[0], cur_cap[0]);//第一次发送的数据包量
	int send2 = min(pre[1] + cur_cap[1], cur_cap[0]);//第二次发送的数据包数最大可能情况

	//判断第一次转发来的数据包是否已被转走
	if (pre[0] - cur_cap[0] > 0)//来的数据包大于当前节点的转发能力
		send2 = min(pre[1] + pre[0] - cur_cap[0], send2);
	else
		send2 = min(pre[1], send2);
	return vector<int> {send1, send2};
}
int main() {
	int k, a;//节点数k 发送包数a
	int res = 0;//两轮最少能转发的数据包
	vector<vector<int>> cap;//cap(k, vector<int>(2)) 节点能力数组 
	cap.push_back(vector<int>{0, 0});//头结点不需考虑能力
	cin >> k;
	int m1, n1;//m1转发能力 n1缓存能力
	char ch;
	for (int i = 0; i < k; i++) {
		cin >> m1 >> ch >> n1;
		cap.push_back(vector<int>{m1, n1});
	}
	cin >> a;

	vector<vector<int>> dp(k + 1, vector<int>(2));//第i个节点两次发送的数据包数
	dp[0][0] = a;//第0个节点第一次发送a个数据包
	dp[0][1] = 0;//第0个节点第二次发送0个数据包

	dp[1] = dpfun(dp[0], cap[1]);
	res = min(dp[0][0] + dp[0][1], dp[1][0] + dp[1][1]);//如果只有一个节点

	if (k == 0)
		cout << a << endl;
	else {
		for (int i = 2; i <= k; i++) {
			vector<int> res1 = dpfun(dp[i - 1], cap[i]);//前一个节点没有故障
			vector<int> res2 = dpfun(dp[i - 2], cap[i]);//前一个节点故障
			dp[i] = res1[0] + res1[1] <= res2[0] + res2[1] ? res1 : res2;
		}
		res = min(dp[k][0] + dp[k][1], dp[k - 1][0] + dp[k - 1][1]);
	cout << res << endl;
	}
	return 0;
}

2021华为笔试第二题

查找知识图谱中的实例知识(100%)

知识图谱是一种结构化的语义网络,用于描述物理世界中的概念及其实例的相关关系。可以把知识图谱看成是一种有向图,图中的点是概念或实例,图中的边是概念及其实例的相关关系。

现定义一种简单的知识图谱

概念:包括父概念及其子概念,通过subClassOf关系关联,父子概念可以有多个层级;实例:仅和概念之间通过instanceOf关系关联: 关系:以三元组的形式表示,三元组是一个以空格为成员间分隔符的字符串。例如"student subClassOf person"表示student是person的子概念,"apple instanceOf fruit"表示apple是概念fruit的实例。给定一个知识图谱,请编写一个方法,可以根据一个概念查找其所有的实例。如果一个概念拥有子概念,那么返回的结果需要包含其所有子概念的实例;如果输入的概念没有实例,则返回字符串"empty"(说明:输出字符串文本不需要包含引号)。

给定的图谱满足以下限制: 1、有向图中不存在环路 2、所有点和关系的定义对大小写敏感

输入描述:输入第1行,表示图谱中关系的数量n,取值范围[1,10000] 从第2行到n+1行,表示图谱中的关系,每一行是一个关系三元组第n+2行,表示待查找的元节点,是关系三元组中存在的点。每行字符的长度不超过100。

3
student subClassOf person 
Tom inslenceOf student 
Marry instanceOf person 
person

输出描述按字典序升序排列的字符串数组,其内容是概念及其子概念的所有实例。

Marry Tom 

解释:student是person的子概念,Tom是student的实例,Marry是person的 实例,Marry的字典序小于Tom,所以返回Marry Tom。

解题思路1:

根据instanceOf查找它的父节点是否为target。

1.不管是 subClassOf还是instancOf,左边的是子节点,右边的是父节点。

2.定义哈希集合hash_set(instance)存储instancOf的子节点(每一对的第一个输入)。

3.定义哈希映射unordered_map(hash)存储所有instanceOf和sunClassOf。

4.根据hash_set遍历其父节点是否能到达目标节点即可,若满足则存入到set中,默认字典排序。若不满足则一直向父关系寻找,直到该关系结束。

5.因为存储满足该实例的节点存在set中,是有序的。所以直接输出,无需排序。

也就是用一个map存储关系,用一个set存储instance。然后遍历每一个instance,如果其父节点,或者一直向父关系遍历,如果能找到与目标概念相等,则该实例满足要求,存在set里。

参考代码1:

#include <bits/stdc++.h>
using namespace std;

int main(int argc,char* argv[]){
    int n;
    cin>>n;
    unordered_map<string,string> hash;//val是父节点
    unordered_set<string> instance;//存储instacnOf

    string s1,s2,s3;
    for(int i=0;i<n;++i){
        cin>>s1>>s2>>s3;
        if(s2=="instanceOf")
            instance.insert(s1);
        hash[s1]=s3;
    }
    string ss;
    cin>>ss;
    set<string> ret;
    for(auto s:instance){
        string s1=s;
        while(hash.count(s1)){
            if(hash[s1]==ss){
                ret.insert(s);
                break;
            }
            s1=hash[s1];
        }
    }
    if(ret.size()==0){
        cout<<"empty"<<endl;
    }else{
        int i=0;
        for(auto s:ret){
            if(i==0) cout<<s;
            else cout<<" "<<s;
            ++i;
        }
    }
    return 0;
}

解题思路2:

递归实现

1.定义两个map,分别存储instance,subClass。

    map<string, vector<string>> subClass;//存储subClassOf关系 可能会一对多
    map<string, vector<string>> instance;//存储instanceOf关系 可能会一对多

2.从子节点递归向上找

参考代码2:

#include<bits/stdc++.h>
using namespace std;

void solve(map<string, vector<string>> &subClass, map<string, vector<string>> &instance, vector<string> &res, string &target) {
	for (string str : instance[target])
		res.push_back(str);
	for (string str : subClass[target])
		solve(subClass, instance, res, str);
	return;
}
int main() {
	int n;
	cin >> n;
	map<string, vector<string>> subClass;//存储subClassOf关系 可能会一对多
	map<string, vector<string>> instance;//存储instanceOf关系 可能会一对多

	for (int i = 0; i < n; i++) {
		string head;
		cin >> head;
		string relation;
		cin >> relation;
		string tail;
		cin >> tail;
		if (relation == "subClassOf")
			subClass[tail].push_back(head);
		else
			instance[tail].push_back(head);
	}
	string target;
	cin >> target;
	vector<string> res;
	solve(subClass, instance, res, target);
	sort(res.begin(), res.end());
	if (res.empty())
		cout << "empty";
	else {
		for (string str : res)
			cout << str << " ";
	}
	cout << endl;
	return 0;
}

2021华为笔试第三题

湖泊连通(100%)

题目描述

地图上有多个湖泊,为增强湖泊的抗暴雨能力,需要在湖泊间挖出通道使得湖泊之间能够连通(对角线视为不连通)。有的陆地是坚硬的石头,挖通需要耗费的精力是普通陆地的2倍,即一个普通格子的长度为1,一个有坚硬石头的格子的长度为2。地图用二维矩阵表示,每个位置只有三种可能,0为湖泊,1为普通陆地,2为坚硬的石头,地图最大为MN。需要返回挖通所有湖泊的最短通道,如果通道不存在的话,返回0 限制:M、N最大为20,湖泊个数不超过11。

输入描述:第一行为M 第二行为N 第三行开始为M*N的地图矩阵

5 
4
0 1 1 0
0 1 0 0
0 1 0 0
0 1 0 1
1 1 1 1

输出描述:返回挖通所有湖泊的最短通道

1

解释:地图上共有2片湖泊,只需要挖通1块陆地,2片湖泊即可连通。

解题思路:

这道题是【斯坦纳树】的经典例题。斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个)点是【关键点】,要求选择一些边使这些点在同一个联通块内,同时要求所选的边的边权和最小。

怎么解决斯坦纳树问题?……其实,就是一种状压DP。

dp[i][j]表示以i号节点为根,当前状态为j(j的二进制中已经与i连通的点对应位置为1)。

这个“以i为根”是哪来的呢?其实i可以是联通块中任意一个点,没有额外限制,只是引入这个i就可以DP了。

当根i不改变时(即合并两个都包含i的联通块)状态转移方程是:

图片

参考代码: 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
    if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
    x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x){
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}

const int INF = 0x3f3f3f3f;
int n, m, K, root, f[101][1111], a[101], ans[11][11];
bool inq[101];
typedef pair<int, int> par;
typedef pair<par, int> rec;
#define fi first
#define se second
#define mp make_pair
#define num(u) (u.fi * m + u.se)
rec pre[101][1111];
const int dx[] = {0, 0, -1, 1};
const int dy[] = {1, -1, 0, 0};
queue<par> que;

bool legal(par u){
    return u.fi >= 0 && u.se >= 0 && u.fi < n && u.se < m;
}
void spfa(int now){
    while(!que.empty()){
 par u = que.front();
 que.pop();
 inq[num(u)] = 0;
 for(int d = 0; d < 4; d++){
     par v = mp(u.fi + dx[d], u.se + dy[d]);
     int nu = num(u), nv = num(v);
     if(legal(v) && f[nv][now] > f[nu][now] + a[nv]){
  f[nv][now] = f[nu][now] + a[nv];
  if(!inq[nv]) inq[nv] = 1, que.push(v);
  pre[nv][now] = mp(u, now);
     }
 }
    }
}
void dfs(par u, int now){
    if(!pre[num(u)][now].se) return;
    ans[u.fi][u.se] = 1;
    int nu = num(u);
    if(pre[nu][now].fi == u) dfs(u, now ^ pre[nu][now].se);
    dfs(pre[nu][now].fi, pre[nu][now].se);
}

int main(){

    read(n), read(m);
    memset(f, 0x3f, sizeof(f));
    for(int i = 0, tot = 0; i < n; i++)
 for(int j = 0; j < m; j++){
     read(a[tot]);
     if(!a[tot]) f[tot][1 << (K++)] = 0, root = tot;
     tot++;
 }
    for(int now = 1; now < (1 << K); now++){
 for(int i = 0; i < n * m; i++){
     for(int s = now & (now - 1); s; s = now & (s - 1))
  if(f[i][now] > f[i][s] + f[i][now ^ s] - a[i]){
      f[i][now] = f[i][s] + f[i][now ^ s] - a[i];
      pre[i][now] = mp(mp(i / m, i % m), s);
  }
     if(f[i][now] < INF)
  que.push(mp(i / m, i % m)), inq[i] = 1;
 }
 spfa(now);
    }
    write(f[root][(1 << K) - 1]), enter;
    dfs(mp(root / m, root % m), (1 << K) - 1);
    for(int i = 0, tot = 0; i < n; i++){
 for(int j = 0; j < m; j++)
     if(!a[tot++]) putchar('x');
     else putchar(ans[i][j] ? 'o' : '_');
 enter;
    }

    return 0;
}

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1.static有什么用途?(请至少说明两种) 1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用 2.引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。 3.描述实时系统的基本特性 在特定时间内完成特定的任务,实时性与可靠性。 4.全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈。 5.什么是平衡二叉树? 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。 6.堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源。 7.什么函数不能声明为虚函数? constructor函数不能声明为虚函数。 8.冒泡排序算法的时间复杂度是什么? 时间复杂度是O(n^2)。 9.写出float x 与“零值”比较的if语句。 if(x>0.000001&&x<-0.000001) 10.Internet采用哪种网络协议?该协议的主要层次结构? Tcp/Ip协议 主要层次结构为: 应用层/传输层/网络层/数据链路层/物理层。 11.Internet物理地址和IP地址转换采用什么协议? ARP (Address Resolution Protocol)(地址解析協議) 12.IP地址的编码分为哪俩部分? IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。 13.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。 循环链表,用取余操作做 14.不能做switch()的参数类型是: switch的参数不能为实型。 1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值(3分) int a = 4; (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++); a = ? 答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a; 改后答案依次为9,10,10,11 2.某32位系统下, C++程序,请计算sizeof 的值(5分). char str[] = “http://www.ibegroup.com/” char *p = str ; int n = 10; 请计算 sizeof (str ) = ?(1) sizeof ( p ) = ?(2) sizeof ( n ) = ?(3) void Foo ( char str[100]){ 请计算 sizeof( str ) = ?(4) } void *p = malloc( 100 ); 请计算 sizeof ( p ) = ?(5) 答:(1)17 (2)4 (3) 4 (4)4 (5)4 3. 回答下面的问题. (4分) (1).头文件中的 ifndef/define/endif 干什么用?预处理 答:防止头文件被重复引用 (2). #i nclude 和 #i nclude “filename.h” 有什么区别? 答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。 (3).在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明? 答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变 量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调 用C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问题。 (4). switch()中不允许的数据类型是? 答:实型 4. 回答下面的问题(6分) (1).Void GetMemory(char **p, int num){ *p = (char *)malloc(num); } void Test(void){ char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); } 请问运行Test 函数会有什么样的结果? 答:输出“hello” (2). void Test(void){ char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL){ strcpy(str, “world”); printf(str); } } 请问运行Test 函数会有什么样的结果? 答:输出“world” (3). char *GetMemory(void){ char p[] = "hello world"; return p; } void Test(void){ char *str = NULL; str = GetMemory(); printf(str); } 请问运行Test 函数会有什么样的结果? 答:无效的指针,输出不确定 5. 编写strcat函数(6分) 已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc); 其中strDest 是目的字符串,strSrc 是源字符串。 (1)不调用C++/C 的字符串库函数,请编写函数 strcat 答: VC源码: char * __cdecl strcat (char * dst, const char * src) { char * cp = dst; while( *cp ) cp++; /* find end of dst */ while( *cp++ = *src++ ) ; /* Copy src to end of dst */ return( dst ); /* return dst */ } (2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值? 答:方便赋值给其他变量 6.MFC中CString是类型安全类么? 答:不是,其它数据类型转换到CString可以使用CString的成员函数Format来转换 7.C++中为什么用模板类。 答:(1)可用来创建动态增长和减小的数据结构 (2)它是类型无关的,因此具有很高的可复用性。 (3)它在编译时而不是运行时检查数据类型,保证了类型安全 (4)它是平台无关的,可移植性 (5)可用于基本数据类型 8.CSingleLock是干什么的。 答:同步多个线程对一个数据类的同时访问 9.NEWTEXTMETRIC 是什么。 答:物理字体结构,用来设置字体的高宽大小 10.程序什么时候应该使用线程,什么时候单线程效率高。 答:1.耗时的操作使用线程,提高应用程序响应 2.并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求。 3.多CPU系统中,使用线程提高CPU利用率 4.改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独 立的运行部分,这样的程序会利于理解和修改。 其他情况都使用单线程。 11.Windows是内核级线程么。 答:见下一题 12.Linux有内核级线程么。 答:线程通常被定义为一个进程中代码的不同执行路线。从实现方式上划分,线程有两 种类型:“用户级线程”和“内核级线程”。 用户线程指不需要内核支持而在用户程序 中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度 和管理线程的函数来控制用户线程。这种线程甚至在象 DOS 这样的操作系统中也可实现 ,但线程的调度需要用户程序完成,这有些类似 Windows 3.x 的协作式多任务。另外一 种则需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部 需求进行创建和撤销,这两种模型各有其好处和缺点。用户线程不需要额外的内核开支 ,并且用户态线程的实现方式可以被定制或修改以适应特殊应用的要求,但是当一个线 程因 I/O 而处于等待状态时,整个进程就会被调度程序切换为等待状态,其他线程得不 到运行的机会;而内核线程则没有各个限制,有利于发挥多处理器的并发优势,但却占 用了更多的系统开支。 Windows NT和OS/2支持内核线程。Linux 支持内核级的多线程 13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理 堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上 14.使用线程是如何防止出现大的波峰。 答:意思是如何防止同时产生大量的线程,方法是使用线程池,线程池具有可以同时提 高调度效率和限制资源使用的好处,线程池中的线程达到最大数时,其他线程就会排队 等候。 15函数模板与类模板有什么区别? 答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化 必须由程序员在程序中显式地指定。 16一般数据库若出现日志满了,会出现什么情况,是否还能使用? 答:只能执行查询等读操作,不能执行更改,备份等写操作,原因是任何写操作都要记 录日志。也就是说基本上处于不能使用的状态。 17 SQL Server是否支持行级锁,有什么好处? 答:支持,设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据 的一致性和准确性,行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不 被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。 18如果数据库满了会出现什么情况,是否还能使用? 答:见16 19 关于内存对齐的问题以及sizof()的输出 答:编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能 地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问 ;然而,对齐的内存访问仅需要一次访问。 20 int i=10, j=10, k=3; k*=i+j; k最后的值是? 答:60,此题考察优先级,实际写成: k*=(i+j);,赋值运算符优先级最低 21.对数据库的一张表进行操作,同时要对另一张表进行操作,如何实现? 答:将操作多个表的操作放入到事务中进行处理 22.TCP/IP 建立连接的过程?(3-way shake) 答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。   第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状 态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个 SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;   第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1) ,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 23.ICMP是什么协议,处于哪一层? 答:Internet控制报文协议,处于网络层(IP层) 24.触发器怎么工作的? 答:触发器主要是通过事件进行触发而被执行的,当对某一表进行诸如UPDATE、 INSERT 、 DELETE 这些操作时,数据库就会自动执行触发器所定义的SQL 语句,从而确保对数 据的处理必须符合由这些SQL 语句所定义的规则。 25.winsock建立连接的主要实现步骤? 答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept() 等待客户端连接。 客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv( ),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。 服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连 接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesock et()关闭套接字。 26.动态连接库的两种方式? 答:调用一个DLL中的函数有两种方法: 1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数 ,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向 系统提供了载入DLL时所需的信息及DLL函数定位。 2.运行时动态链接(run-time dynamic linking),运行时可以通过LoadLibrary或Loa dLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的 出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了 。 27.IP组播有那些好处? 答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧 消耗和网络拥挤问题。组播是一种允许一个或多个发送者(组播源)发送单一的数据包 到多个接收者(一次的,同时的)的网络技术。组播可以大大的节省网络带宽,因为无 论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。所以说组播 技术的核心就是针对如何节约网络资源的前提下保证服务质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子木呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值