深拷贝,浅拷贝
浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存
深拷贝:创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象,是值而不是引用
继承
父继承子
红黑树
1.
红黑树有以下性质:
1.每个结点不是红色就是黑色。
2.根结点是黑色的。
3.如果一个结点是红色的,则它的两个孩子结点是黑色的。
4.对于每个结点,从该结点到其所有后代叶子结点的简单路径上,均包含相同数目的黑色结点。
5.每个叶子结点都是黑色的(此处的叶子结点指定是空结点)
2.
红黑树如何确保从根到叶子的最长可能路径不会超过最短可能路径的两倍
根据红黑树的性质3可以得出,红黑树当中不会出现连续的红色结点,而根据性质4又可以得出,从某一结点到其后代叶子结点的所有路径上包含的黑色结点的数目是相同的。
我们假设在红黑树中,从根到叶子的所有路径上包含的黑色结点的个数都是N个,那么最短路径就是全部由黑色结点构成的路径,即长度为N。
而最长可能路径就是由一黑一红结点构成的路径,该路径当中黑色结点与红色结点的数目相同,即长度为2N.
3.红黑树与AVL树的比较
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(logN),但是红黑树与AVL树控制二叉树平衡的方式不同:
AVL树是通过控制左右高度差不超过1来实现二叉树平衡的,实现的是二叉树的严格平衡。
红黑树是通过控制结点的颜色,从而使得红黑树当中最长可能路径不超过最短可能路径的2倍,实现的是近平衡。
socket编程
服务端
1.创建socket
2.bind()
3.listen()
4.accept()
5.send() recv()
6.关闭网络连接
7.关闭监听
客户端
1.创建socket
2.bind()
3.connect()
4.send()
epoll
内核底层是红黑树,红黑树然后将变化的放到双链表里面
epoll_create函数创建一个文件,返回一个文件描述符fd
通过epoll_ctl函数将该socket号和监听的事件(listen)写入fd中
循环epoll_wait函数进行监听,返回就绪事件序列的长度
边沿触发和水平触发
边沿触发:当文件描述符关联的读内核缓冲区发生变化,才发出可读信号进行通知,因此需要设置文件为非阻塞模式
水平触发:只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就已知发出可读信号通知
举个例子:
1.读缓冲区刚开始是空的
2.读缓冲区写入2KB数据
3.水平触发和边缘触发模式此时都会发出可读信号
4.收到信号通知后,读取了1kb的数据,读缓冲区还剩余1KB数据
5.水平触发会再次进行通知,而边缘触发不会再进行通知
TCP/IP四层
四层包括:链路层,网络层,传输层,应用层
arp:ip --> 物理地址
rarp: 物理地址-->ip
网络层:负责将数据传输到目标地址,寻找适合的路径到达对方计算机,并把数据帧传送给对方
ip:
icmp:
igmp:
传输层:提供端到端的服务 tcp(传输效率低,准确), udp(不准确)
应用层:http ftp smtp telnet
三次握手,四次挥手
Proactor模式
Proactor模式将所有将所有I/O操作都交给主线程和内核来处理,工作线程仅仅负责业务逻辑
进程通信
管道,消息队列,共享内存,信号,套接字
管道:
半双工通信,如果想实现相互通信(全双工通信),必须创建两个管道
另外,通过管道符|创建的的管道是匿名管道,用完了就被自动销毁。并且,匿名管道只能在具有亲缘关系(父子进程)的进程间使用,也就是说,匿名管道只能用于父子进程之间的通信。
共享内存:
两个不同进程的逻辑地址通过页表映射到物理空间的同一区域,它们所共同指向的这块区域就是共享内存。对于共享内存机制来说,仅在建立共享内存区域时需要系统调用,一旦建立共享内存,所有的访问东渡可以作为常规内存访问,无需借助内核。这样,数据就不需要在进程之间来回拷贝。
信号:
信号是进程通信机制中唯一的异步通信机制,它可以在任何时候发送信号给某个进程。通过发送指定新年好来通知某个异步事件的发送,以迫使进程执行信号处理程序。信号处理完毕后,被终端进程将回复执行。
linux中的信号
kill -l
socket
是网络通信的基石