笔试题整理【4】

一、四层网络模型与七层网络模型(每层写出对应的三个协议)?

七层网络模型:应用层   表示层   会话层   传输层   网际层   数据链接层   物理层

 四层网络模型:

应用层:TFTP、FTP、Telnet、DNS

传输层:TCP、UDP

网际层:ICMP、IP、ARP、RARP

网络接口层:FDDI、PDN、PPP、IEEE802.1A(各种通信网络接口)


二、用两个栈实现一个队列的功能?要求给出算法和思路?

思路:入队:将元素进栈 A 

出队:判断栈 B 是否为空,如果为空,则将栈 A  中所有元素 pop,并 push 进栈 B,栈 B 出栈;

如果不为空,栈 B 直接出栈


算法:

class Solution
{
public:
	void push(int node)
	{
		stack1.push(node);
	}

	int pop()
	{
		if (stack2.empty())
		{
			while (!stack1.empty())
			{
				stack2.push(stack1.top());
				stack1.pop();
			}
		}

		int a = stack2.top();
		stack2.pop();

		return a;
	}

private:
	stack<int> stack1;
	stack<int> stack2;
};


说到这了,那用两个队列实现一个栈呢

思路:队列是先进先出,所以要拿到队列中最后压入的元素,只能每次将队列中元素 pop 到只剩一个,

此时这个元素为最后压入队的元素,循环往复


算法:

class CStack      //两个队实现一个栈
{
public:
	void push(int node)
	{
		if (!q1.empty())
		{
			q1.push(node);
		}
		else
		{
			q2.push(node);
		}
	}

	int deleteHead()
	{
		int ret = 0;
		if (q1.empty())
		{
			int i = q2.size();

			while (i > 1)
			{
				q1.push(q2.front());
				q2.pop();
				--i;
			}

			ret = q2.front();
			q2.pop();
		}
		else
		{
			int i = q1.size();

			while (i > 1)
			{
				q2.push(q1.front());
				q1.pop();
				--i;
			}

			ret = q1.front();
			q1.pop();
		}

		return ret;
	}


private:
	queue<int> q1;
	queue<int> q2;
};




三、论述含参数的宏和函数的优缺点?

1、函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换

2、函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开

时并不分配内存单元,不进行值得传递处理,也没有返回值的概念

3、对函数中的实参和形参都要定义类型,二者的类型要一致,如不一致,应进行类型转换;而宏不

存在这样的问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可

宏定义时,字符串可以是任何类型的数据

4、调用函数只可得到一个返回值,而用宏可以设法得到几个结果

5、使用宏次数多时,宏展开后源程序长,因为每次展开都会使程序增长,而函数调用不会使程序增长

6、宏替换不占用运行时间、只占编译时间;而函数调用则占运行时间

一般来说,用宏来代表简短的表达式比较合适


四、结构与联合有何区别?

1、在存储多个成员信息时,编译器会自动给 struct 每个成员分配存储空间,struct 可以存储多个成员信息

而 union 每个成员会用同一个存储空间,只能存储最后一个成员的信息

2、都是由多个不同数据类型成员组成,但在任何同一时刻,Union 只存放了一个被先选中的成员,而结构体

的所有成员都存在

3、对于  Union 的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于 struct 的不同成员

赋值是互不影响的


五、引用与指针有什么区别?

1、初始化要求不同。引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化

可以在定义后面的任何地方重新赋值

2、可修改性不同。引用一旦被初始化为一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以

改变为指向另一个对象。给引用赋值并不是改变它和原始对象的绑定关系

3、不存在 NULL 引用,引用不能使用指向空值的引用,它必须指向某个对象;而指针则可以是NULL,可以把指针

指向任意的对象,所以指针更加灵活

4、使用引用之前不需要测试它;而指针需要经常测试;因此使用引用的效率比指针高

5、如果是一旦指向一个对象后就不会改变指向,那么应该使用引用,如果存在指向 NULL 或在不同时刻指向不同

的对象这些可能性,应该使用指针


六、C++建议用 const 来代替宏常量   

1、const 常量是在编译的时候进行处理,会做类型检查

宏常量不会做类型检查,在预处理期间进行完全替换

2、C++ const 修饰的是一个常量,常量的值会放到符号表中去,如果对 const 修饰的变量进行取地址操作,则编译器

会在内存中为这个变量分配空间,但这个空间不使用

3、宏常量不会做作用域检查,const 常量会;宏常量的作用域定义的位置开始到文件结束

宏是可以撤销的


七、TCP三次握手和四次挥手

TCP 是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接

tcp 标志位

SYN   建立连接

ACK   表示响应、确认

PSH   表示 DATA 数据传输

FIN    关闭连接

RST   表示连接重置

URG   紧急指针字段值有效


三次握手:

第一次握手:客户端发送 syn 包到服务器,并确认进入 SYN_SEND状态,等待服务器确认

第二次握手:服务器收到 syn 包,必须确认客户的 SYN ,同时自己发送一个 SYN 包,即 SYN+ACK包,此时服务器进入 SYN_RECV状态

第三次握手:客户端收到服务器的 SYN+ACK包,向服务器发送确认包 ACK ,此包发送完毕,完成三次握手


四次挥手:

第一次挥手:客户端发送一个 FIN 包,请求关闭连接

第二次挥手:服务器收到 FIN 包,发送一个 ACK 给客户端,

第三次挥手:服务器发送给客户端一个 FIN ,结束该报文段

第四次挥手:客户端收到 FIN 后,发送一个 ACK 给服务器,确认该结束报文段




猜你喜欢

转载自blog.csdn.net/ljf_djcrs/article/details/79431735