2018年2月26日

用信号量实现进程互斥示例和解决哲学家就餐问题

摘要: 一、我们在前面讲进程间通信的时候提到过进程互斥的概念,下面写个程序来模拟一下,程序流程如下图: 即父进程打印字符O,子进程打印字符X,每次打印一个字符后要sleep 一下,这里要演示的效果是,在打印程序的边界有PV操作,故每个进程中间sleep 的时间即使时间片轮转到另一进程,由于资源不可用也不会穿 阅读全文

posted @ 2018-02-26 14:40 AlanTu 阅读(2435) 评论(0) 推荐(0)

封装一个信号量集操作函数的工具

摘要: 信号量的概念参见这里。 与消息队列和共享内存一样,信号量集也有自己的数据结构: struct semid_ds { struct ipc_perm sem_perm; /* Ownership and permissions */ time_t sem_otime; /* Last semop ti 阅读全文

posted @ 2018-02-26 14:38 AlanTu 阅读(578) 评论(0) 推荐(0)

System V 共享内存 和 系列函数

摘要: 跟消息队列一样,共享内存也有自己的数据结构,如下: struct shmid_ds { struct ipc_perm shm_perm; /* Ownership and permissions */ size_t shm_segsz; /* Size of segment (bytes) */ 阅读全文

posted @ 2018-02-26 14:36 AlanTu 阅读(373) 评论(0) 推荐(0)

共享内存简介和mmap 函数

摘要: 一、共享内存简介 共享内存区是最快的IPC形式,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。 即每个进程地址空间都有一个共享存储器的映射区,当这块区域都映射到相同的真正的物理地址空间时,可以通过这块区域进行数据交换,例如共享库就是这么实现的,很多进 阅读全文

posted @ 2018-02-26 14:34 AlanTu 阅读(2124) 评论(0) 推荐(0)

消息队列实现回射客户/服务器和 msgsnd、msgrcv 函数

摘要: 一、msgsnd 和 msgrcv 函数 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> 功能:把一条消息添加到消息队列中 原型 int msgsnd(int msqid, const void *msgp, size 阅读全文

posted @ 2018-02-26 14:33 AlanTu 阅读(1599) 评论(0) 推荐(0)

消息队列内核结构和msgget、msgctl 函数

摘要: 一、消息队列 1、消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2、每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 3、消息队列与管道不同的是,消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出。 4、消息队列也有管道一样的不足,就 阅读全文

posted @ 2018-02-26 14:30 AlanTu 阅读(6087) 评论(0) 推荐(0)

进程间通信概述

摘要: 一、顺序程序与并发程序特征 顺序程序特征 顺序性 封闭性:(运行环境的封闭性) 确定性 可再现性 并发程序特征 共享性 并发性 随机性 二、进程互斥 1、由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥 2、系统中某些资源一次只允许一个进程使 阅读全文

posted @ 2018-02-26 14:27 AlanTu 阅读(285) 评论(0) 推荐(0)

通过UNIX域套接字传递描述符和 sendmsg/recvmsg 函数

摘要: 在前面我们介绍了UNIX域套接字编程,更重要的一点是UNIX域套接字可以在同一台主机上各进程之间传递文件描述符。 下面先来看两个函数: #include <sys/types.h> #include <sys/socket.h> ssize_t sendmsg(int sockfd, const s 阅读全文

posted @ 2018-02-26 14:25 AlanTu 阅读(1458) 评论(0) 推荐(0)

UNIX域套接字编程和socketpair 函数

摘要: 一、UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX D 阅读全文

posted @ 2018-02-26 14:23 AlanTu 阅读(3343) 评论(0) 推荐(1)

基于UDP协议的网络程序

摘要: 一、下图是典型的UDP客户端/服务器通讯过程 下面依照通信流程,我们来实现一个UDP回射客户/服务器 #include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len 阅读全文

posted @ 2018-02-26 14:21 AlanTu 阅读(2428) 评论(0) 推荐(0)

epoll 系列函数简介、与select、poll 的区别

摘要: 一、epoll 系列函数简介 #include <sys/epoll.h> int epoll_create(int size); int epoll_create1(int flags); int epoll_ctl(int epfd, int op, int fd, struct epoll_e 阅读全文

posted @ 2018-02-26 14:20 AlanTu 阅读(2730) 评论(0) 推荐(0)

select函数的并发限制和 poll 函数应用举例

摘要: 一、用select实现的并发服务器,能达到的并发数,受两方面限制 1、一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n来调整或者使用setrlimit函数设置, 但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/fi 阅读全文

posted @ 2018-02-26 14:18 AlanTu 阅读(719) 评论(0) 推荐(0)

套接字I/O超时设置方法和用select实现超时

摘要: 注:如无特殊说明,sockfd 原始状态都是阻塞的。 一、使用alarm 函数设置超时 C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 void handler(int sig) { } signal(SIGALRM, handler); alarm(5); int r 阅读全文

posted @ 2018-02-26 14:16 AlanTu 阅读(1090) 评论(0) 推荐(0)

shutdown 与 close 函数 的区别

摘要: 假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client(其实不一定会发送FIN段,后面再说),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 阅读全文

posted @ 2018-02-26 14:13 AlanTu 阅读(311) 评论(0) 推荐(0)

使用select函数改进客户端/服务器端程序

摘要: 一、当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ubuntu:~/Documents/code/linux_programming/UNP/socket 阅读全文

posted @ 2018-02-26 14:11 AlanTu 阅读(1571) 评论(0) 推荐(0)

五种I/O模型和select函数简介

摘要: 一、五种I/O模型 1、阻塞I/O 我们在前面所说的I/O模型都是阻塞I/O,即调用recv系统调用,如果没有数据则阻塞等待,当数据到来则将数据从内核空间(套接口缓冲区)拷贝到用户空间(recv函数提供的buf),然后recv返回,进行数据处理。 2、非阻塞I/O 我们可以使用 fcntl(fd, 阅读全文

posted @ 2018-02-26 14:08 AlanTu 阅读(937) 评论(0) 推荐(0)

一个进程发起多个连接和gethostbyname等函数

摘要: 一、在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就可以让一个客户端发起多个连 接,然后只利用其中一个连接发送数据。 先来认识一个函数getsockname #include <sys/socket.h> int getsockname(int 阅读全文

posted @ 2018-02-26 14:05 AlanTu 阅读(640) 评论(0) 推荐(0)

利用recv和readn函数实现readline函数

摘要: 在前面的文章中,我们为了避免粘包问题,实现了一个readn函数读取固定字节的数据。如果应用层协议的各字段长度固定,用readn来读是非常方便 的。例如设计一种客户端上传文件的协议,规定前12字节表示文件名,超过12字节的文件名截断,不足12字节的文件名用'\0'补齐,从第13字节开始是 文件内容,上 阅读全文

posted @ 2018-02-26 14:03 AlanTu 阅读(1012) 评论(1) 推荐(2)

tcp流协议产生的粘包问题和解决方案

摘要: 我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议 阅读全文

posted @ 2018-02-26 14:01 AlanTu 阅读(908) 评论(0) 推荐(0)

使用fork并发处理多个client的请求和对等通信p2p

摘要: 一、在前面讲过的回射客户/服务器程序中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现。网络服务器通常用fork来同时服务多个客户端,父进程专门负责监听端口,每次accept一个新的客户端连接就f 阅读全文

posted @ 2018-02-26 13:59 AlanTu 阅读(743) 评论(0) 推荐(0)

最简单的回射客户/服务器程序、time_wait 状态

摘要: 下面通过最简单的客户端/服务器程序的实例来学习socket API。 echoser.c 程序的功能是从客户端读取字符然后直接回射回去。 C++ Code 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 阅读全文

posted @ 2018-02-26 13:56 AlanTu 阅读(404) 评论(0) 推荐(0)

C/S程序的一般流程和基本socket函数

摘要: 一、基于TCP协议的网络程序 下图是基于TCP协议的客户端/服务器程序的一般流程: 服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服 阅读全文

posted @ 2018-02-26 13:54 AlanTu 阅读(1021) 评论(0) 推荐(0)

socket概述和字节序、地址转换函数

摘要: 一、什么是socket socket可以看成是用户进程与内核网络协议栈的编程接口。 socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信。 socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及以后要讲的UNIX Domain So 阅读全文

posted @ 2018-02-26 13:53 AlanTu 阅读(1310) 评论(0) 推荐(0)

分析一帧基于UDP的TFTP协议帧

摘要: 下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度。 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00 IP首部 000 阅读全文

posted @ 2018-02-26 13:52 AlanTu 阅读(1366) 评论(0) 推荐(0)

IP数据报格式和IP地址路由

摘要: 一、IP数据报格式 IP数据报格式如下: 注:需要注意的是网络数据包以大端字节序传输,当然头部也得是大端字节序,也就是说: The most significant bit is numbered 0 at the left, and the least significant bit of a 3 阅读全文

posted @ 2018-02-26 13:49 AlanTu 阅读(3310) 评论(0) 推荐(0)

利用ARP和ICMP协议解释ping命令

摘要: 一、MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit)。如果IP层有一个数据报要传,而且数据的长度比链路层的MTU还大,那么IP层就要进行分片(Fragmentat 阅读全文

posted @ 2018-02-26 13:48 AlanTu 阅读(6371) 评论(0) 推荐(0)

TCP/IP协议栈与数据报封装

摘要: 一、ISO/OSI参考模型 OSI(open system interconnection)开放系统互联模型是由ISO(International Organization for Standardization)国际标准化组织定义的网络分层模型,共七层,如下图。 物理层(Physical Laye 阅读全文

posted @ 2018-02-26 13:46 AlanTu 阅读(3190) 评论(0) 推荐(0)

从汇编角度来理解linux下多层函数调用堆栈运行状态

摘要: 我们用下面的C代码来研究函数调用的过程。 C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int bar(int c, int d) { int e = c + d; return e; }int foo(int a, int b) { return  阅读全文

posted @ 2018-02-26 13:36 AlanTu 阅读(572) 评论(0) 推荐(0)

read/write函数与(非)阻塞I/O的概念

摘要: 一、read/write 函数 read函数从打开的设备或文件中读取数据。 #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件 阅读全文

posted @ 2018-02-26 13:34 AlanTu 阅读(5584) 评论(0) 推荐(0)

可重入函数、线程安全、volatile

摘要: 一、 POSIX 中对可重入和线程安全这两个概念的定义: Reentrant Function:A function whose effect, when called by two or more threads,is guaranteed to be as if the threads each 阅读全文

posted @ 2018-02-26 13:32 AlanTu 阅读(338) 评论(0) 推荐(0)

Linux进程地址空间和虚拟内存

摘要: 一、虚拟内存 先来看一张图(来自《Linux内核完全剖析》),如下: 分段机制:即分成代码段,数据段,堆栈段。每个内存段都与一个特权级相关联,即0~3,0具有最高特权级(内核),3则是最低特权级(用户),每当程序试图访问(权限又分为可读、可写和可执行)一个段时,当前特权级CPL就会与段的特权级进行比 阅读全文

posted @ 2018-02-26 13:30 AlanTu 阅读(2413) 评论(0) 推荐(0)

C 标准库IO缓冲区和内核缓冲区的区别

摘要: 1.C标准库的I/O缓冲区 UNIX的传统 是Everything is a file,键盘、显示器、串口、磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也可以像普通文件(保存在磁盘上的文件)一样打开、读、写和关闭,使用的函数接口是相同的。用户程序调用C标准I/O库函数读写 阅读全文

posted @ 2018-02-26 13:28 AlanTu 阅读(2302) 评论(1) 推荐(1)

文件描述符file descriptor与inode的相关知识

摘要: 每个进程在Linux内核中都有一个task_struct结构体来维护进程相关的 信息,称为进程描述符(Process Descriptor),而在操作系统理论中称为进程控制块 (PCB,Process Control Block)。task_struct中有一个指针(struct files_str 阅读全文

posted @ 2018-02-26 13:26 AlanTu 阅读(689) 评论(0) 推荐(0)

C 标准IO 库函数与Unbuffered IO函数

摘要: 先来看看C标准I/O库函数是如何用系统调用实现的。 fopen(3) 调用open(2)打开指定的文件,返回一个文件描述符(就是一个int 类型的编号),分配一 个FILE 结构体, 通常里面包含了: 文件fd 缓冲区指针 缓冲区长度 当前缓冲区读取长度 出错标志 返回这 个FILE 结构体的地址。 阅读全文

posted @ 2018-02-26 13:25 AlanTu 阅读(442) 评论(0) 推荐(0)

计算机体系结构一点基础知识

摘要: 下面这张图来自《深入理解计算机系统》: IO桥部分一般还分为北桥和南桥,北桥当然是靠上的了。 •CPU –主频: CPU的时钟频率,内核工作的时钟频率 –外频: 系统总线的工作频率 –倍频: CPU外频与主频相差的倍数 –前端总线: 将CPU连接到北桥芯片的总线 –总线频率: 与外频相同或者是外频的 阅读全文

posted @ 2018-02-26 13:24 AlanTu 阅读(1320) 评论(0) 推荐(1)

套接字socket 的地址族和类型、工作原理、创建过程

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 11:01 AlanTu 阅读(2018) 评论(0) 推荐(0)

Ext2文件系统布局,文件数据块寻址,VFS虚拟文件系统

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 11:00 AlanTu 阅读(1125) 评论(0) 推荐(0)

内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:58 AlanTu 阅读(1708) 评论(0) 推荐(0)

X86 寻址方式、AT&T 汇编语言相关知识、AT&T 与 Intel 汇编语言的比较、gcc 嵌入式汇编

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:56 AlanTu 阅读(1482) 评论(0) 推荐(0)

进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:53 AlanTu 阅读(1510) 评论(0) 推荐(0)

时间系统、进程的调度与切换

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:50 AlanTu 阅读(2928) 评论(0) 推荐(0)

进程控制块PCB结构 task_struct 描述

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:49 AlanTu 阅读(1360) 评论(0) 推荐(0)

中断机制和中断描述符表、中断和异常的处理

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:47 AlanTu 阅读(1682) 评论(0) 推荐(0)

80386的分段机制、分页机制和物理地址的形成

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:46 AlanTu 阅读(948) 评论(0) 推荐(0)

80386的各种寄存器一览

摘要: 注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早 阅读全文

posted @ 2018-02-26 10:42 AlanTu 阅读(2666) 评论(0) 推荐(0)

平衡二叉树AVL - 插入节点后旋转方法分析

摘要: 平衡二叉树 AVL( 发明者为Adel'son-Vel'skii 和 Landis)是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1。 首先我们知道,当插入一个节点,从此插入点到树根节点路径上的所有节点的平衡都可能被打破,如何解决这个问题呢? 这里不讲大多数书上提的什么平衡因子,什 阅读全文

posted @ 2018-02-26 10:40 AlanTu 阅读(687) 评论(0) 推荐(0)

十种排序算法总结

摘要: 首先声明一下,本文只对十种排序算法做简单总结,并参照一些资料给出自己的代码实现,并没有对某种算法理论讲解,更详细的 了解可以参考以下资料(本人参考): 1、《data structure and algorithm analysis in c 》 2、《大话数据结构》 3、http://blog.c 阅读全文

posted @ 2018-02-26 10:38 AlanTu 阅读(461) 评论(0) 推荐(0)

散列表(四)冲突处理的方法之开地址法: 二次探测再散列的实现

摘要: 前面的文章分析了开地址法的其中一种:线性探测再散列,这篇文章来讲开地址法的第二种:二次探测再散列 (二)、二次探测再散列 为改善“堆积”问题,减少为完成搜索所需的平均探查次数,可使用二次探测法。 通过某一个散列函数对表项的关键码 x 进行计算,得到桶号,它是一个非负整数。 若设表的长度为TableS 阅读全文

posted @ 2018-02-26 10:35 AlanTu 阅读(16081) 评论(0) 推荐(0)

散列表(三)冲突处理的方法之开地址法: 线性探测再散列的实现

摘要: 二、开地址法 基本思想:当关键码key的哈希地址H0 = hash(key)出现冲突时,以H0为基础,产生另一个哈希地址H1 ,如果H1仍然冲突,再以H0 为基础,产生另一个哈希地址H2 ,…,直到找出一个不冲突的哈希地址Hi ,将相应元素存入其中。这种方法有一个通用的再散列函 数形式: 其中H0 阅读全文

posted @ 2018-02-26 10:33 AlanTu 阅读(16313) 评论(0) 推荐(0)

散列表(二)冲突处理的方法之链地址法的实现: 哈希查找

摘要: 首先需要澄清的一点是,这里讲的是hash table/hash map ,即数据项所存储的表要用数组来实现。 一、链地址法 这种基本思想:将所有哈希地址为i 的元素构成一个称为同义词链的链表,并将链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在 同义词链中进行。 该散列方法首先对关键 阅读全文

posted @ 2018-02-26 10:31 AlanTu 阅读(968) 评论(0) 推荐(0)

散列表(一)散列表概念、散列函数构造方法、常见字符串哈希函数: 测试冲突

摘要: 一、散列表基本概念 1、散列表(hash table) ,也叫哈希表,是根据关键码而直接进行访问的数据结构。也就是说,它通过把关键码映射到表中一个位置 来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 2、若结构中存在关键码为x的记录,则必定在hash(x)的存储位 阅读全文

posted @ 2018-02-26 10:30 AlanTu 阅读(1402) 评论(0) 推荐(0)

二叉排序树 - 删除节点策略及其图形化(二叉树查找)

摘要: 二叉排序树(BST,Binary Sort Tree)具有这样的性质:对于二叉树中的任意节点,如果它有左子树或右子树,则该节点的数据成员大于左子树所有节点的数据成员,且小于右子树所有节点的数据成员。排序二叉树的中序遍历结果是从小到大排列的。 二叉排序树的查找和插入比较好理解,主要来看一下删除时的情况 阅读全文

posted @ 2018-02-26 10:28 AlanTu 阅读(15850) 评论(0) 推荐(0)

静态查找表 - 顺序查找、二分查找、插值查找、斐波纳契查找

摘要: 查找表(Search table)是由同一类型的数据元素(或记录)构成的集合。关键字(key)是数据元素中某个数据项的值,又称为键值,用它可以表示一个数据元素,也可以标识一个记录的数据项(字段),称之为关键码。若此关键字可以唯一地标识一个记录,则称此关键字为主关键字(primary key)。而对于 阅读全文

posted @ 2018-02-26 10:27 AlanTu 阅读(565) 评论(0) 推荐(0)

AOE网与关键路径简介

摘要: 前面我们说过的拓扑排序主要是为解决一个工程能否顺序进行的问题,但有时我们还需要解决工程完成需要的最短时间问题。如果我们要对一个流程图获得最短时间,就必须要分析它们的拓扑关系,并且找到当中最关键的流程,这个流程的时间就是最短时间。 在前面讲了AOV网的基础上,来介绍一个新的概念。在一个表示工程的带权有 阅读全文

posted @ 2018-02-26 10:25 AlanTu 阅读(5648) 评论(1) 推荐(0)

AOV网与拓扑排序

摘要: 在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex Network)。AOV网中的弧表示活动之间存在的某种制约关系,AOV网中不能存在回路,让某个活动的开始要以自己完成作为先决条件,显然是不可 阅读全文

posted @ 2018-02-26 10:23 AlanTu 阅读(3875) 评论(1) 推荐(1)

最短路径 - 弗洛伊德(Floyd)算法

摘要: 为了能讲明白弗洛伊德(Floyd)算法的主要思想,我们先来看最简单的案例。图7-7-12的左图是一个简单的3个顶点的连通网图。 我们先定义两个二维数组D[3][3]和P[3][3], D代表顶点与顶点的最短路径权值和的矩阵。P代表对应顶点的最短路径的前驱矩阵。在未分析任何顶点之前,我们将D命名为D( 阅读全文

posted @ 2018-02-26 10:20 AlanTu 阅读(686) 评论(0) 推荐(0)

最短路径 - 迪杰斯特拉(Dijkstra)算法

摘要: 对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点。最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法。本文先来讲第一种,从某个源点到其余各顶点的最短路径问题。 这是一个按路径长度递增的次序产生最 阅读全文

posted @ 2018-02-26 10:17 AlanTu 阅读(696) 评论(0) 推荐(0)

图解最小生成树 - 克鲁斯卡尔(Kruskal)算法

摘要: 我们在前面讲过的《克里姆算法》是以某个顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的。同样的思路,我们也可以直接就以边为目标去构建,因为权值为边上,直接找最小权值的边来构建生成树也是很自然的想法,只不过构建时要考虑是否会形成环而已,此时我们就用到了图的存储结构中的边集数组结构,如图7-6- 阅读全文

posted @ 2018-02-26 10:13 AlanTu 阅读(3201) 评论(0) 推荐(0)

图解最小生成树 - 普里姆(Prim)算法

摘要: 我们在图的定义中说过,带有权值的图就是网结构。一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边。所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接起来,并且使得权值的和最小。综合以上两个概念,我们可以得出:构造连通网的最小代价生成树,即最小生成树 阅读全文

posted @ 2018-02-26 10:11 AlanTu 阅读(6323) 评论(0) 推荐(0)

图 - 广度优先遍历

摘要: 图的遍历和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历(Traverse Graph)。 图的遍历方法一般有两种,第一种是我们在前面讲过的《深度优先遍历(Depth First Search)》,也有称为深度优先搜索,简称为DFS。第二 阅读全文

posted @ 2018-02-26 10:09 AlanTu 阅读(5695) 评论(0) 推荐(0)

图 - 深度优先遍历

摘要: 图的遍历和树的遍历类似,我们希望从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历(Traverse Graph)。 图的遍历方法一般有两种,第一种是深度优先遍历(Depth First Search),也有称为深度优先搜索,简称为DFS。第二种是《广度优先遍历( 阅读全文

posted @ 2018-02-26 10:07 AlanTu 阅读(502) 评论(0) 推荐(0)

图 - 存储结构之邻接表

摘要: 对于图来说,邻接矩阵是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。因此我们考虑另外一种存储结构方式:邻接表(Adjacency List),即数组与链表相结合的存储方法。 邻接表的处理方法是这样的。 1、图中顶点用一个一维数组存储,另外,对于 阅读全文

posted @ 2018-02-26 10:06 AlanTu 阅读(5557) 评论(0) 推荐(0)

图 - 存储结构之邻接矩阵

摘要: 图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维的数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 我们来看一个实例,图7-4-2的左图就是一个无向图。 我们再来看一个有向图样例 阅读全文

posted @ 2018-02-26 10:04 AlanTu 阅读(504) 评论(0) 推荐(0)

图 - 定义和术语总结

摘要: 一、图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。在图中的数据元素,我们称之为顶点(Vertex),顶点集合有穷非空。在图中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是 阅读全文

posted @ 2018-02-26 10:03 AlanTu 阅读(327) 评论(0) 推荐(0)

线索二叉树

摘要: 我们知道满二叉树只是一种特殊的二叉树,大部分二叉树的结点都是不完全存在左右孩子的,即很多指针域没有被充分地利用。另一方面我们在对一棵二叉树做某种次序遍历的时候,得到一串字符序列,遍历过后,我们可以知道结点之间的前驱后继关系,也就是说,我们可以很清楚地知道任意一个结点,它的前驱和后继是哪一个。可是这是 阅读全文

posted @ 2018-02-26 10:02 AlanTu 阅读(272) 评论(0) 推荐(0)

二叉树 - 遍历和存储结构

摘要: 在《二叉树的定义和性质》中我们已经认识了二叉树这种数据结构。我们知道链表的每个节点可以有一个后继,而二叉树(Binary Tree)的每个节点可以有两个后继。比如这样定义二叉树的节点: typedef struct node *link; struct node { unsigned char it 阅读全文

posted @ 2018-02-26 10:00 AlanTu 阅读(266) 评论(0) 推荐(0)

迷宫问题 - 队列与广度优先搜索

摘要: 队列也是一组元素的集合,也提供两种基本操作:Enqueue(入队)将元素添加到队尾,Dequeue(出队)从队头取出元素并返回。就像排队买票一样,先来先服务,先入队的人也是先出队的,这种方式称为FIFO(First In First Out,先进先出),有时候队列本身也被称为FIFO。 下面我们用队 阅读全文

posted @ 2018-02-26 09:59 AlanTu 阅读(1754) 评论(0) 推荐(0)

迷宫问题 - 堆栈与深度优先搜索

摘要: 堆栈的访问规则被限制为Push和Pop两种操作,Push(入栈或压栈)向栈顶添加元素,Pop(出栈或弹出)则取出当前栈顶的元素,也就是说,只能访问栈顶元素而不能访问栈中其它元素。 现在我们用堆栈解决一个有意思的问题,定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0 阅读全文

posted @ 2018-02-26 09:58 AlanTu 阅读(1173) 评论(0) 推荐(0)

Solutions for the Maximum Subsequence Sum Problem

摘要: The maximum subarray problem is the task of finding the contiguous subarray within a one-dimensional array of numbers (containing at least one positiv 阅读全文

posted @ 2018-02-26 09:57 AlanTu 阅读(175) 评论(0) 推荐(0)

单链表 - 插入和删除操作

摘要: 下图展示了单链表的基本结构: head指针是链表的头指针,指向第一个节点,每个节点的next指针域指向下一个节点,最后一个节点的next指针域为NULL,在图中用0表示。 下面先来看程序(栈的链式存储实现,另外一个实现点这里)和对应的输出(注意输出前进行了链表反转(见《单链表反转》,否则程序后面的w 阅读全文

posted @ 2018-02-26 09:51 AlanTu 阅读(3070) 评论(0) 推荐(0)

双向链表实现队列与循环链表

摘要: 一、双向链表(double linked list)如图26.5,是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。双向链表的基本操作与单链表基本一样,除了插入和删除的时候需要更改两个指针变量,需要注意的是修改的顺序很重要,插入如图3-14-5,删除如图3-14-6。 链表的delete操作 阅读全文

posted @ 2018-02-26 09:48 AlanTu 阅读(3215) 评论(0) 推荐(0)

二叉树 - 定义和性质以及特殊二叉树

摘要: 一、二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。如图1就是一棵二叉树 图1 二叉树的特点: (1)每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。 (2)左 阅读全文

posted @ 2018-02-26 09:46 AlanTu 阅读(5691) 评论(0) 推荐(0)

树 - 定义和基本概念

摘要: 一、树(Tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任意一棵非空树中:(1)有且仅有一个特定的称为根(root)的结点。 (2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,....,Tm, 其中每一个集合本身又是一棵树,并且称为根的子树(SubTree),如 阅读全文

posted @ 2018-02-26 09:44 AlanTu 阅读(2933) 评论(0) 推荐(0)

字符串 - KMP模式匹配

摘要: 在朴素的模式匹配算法中,主串的pos值(i)是不断地回溯来完成的(见字符串的基本操作中的Index函数)。而计算机的大仙们发现这种回溯其实可以是不需要的。既然i值不回溯,也就是不可以变小,那么考虑的变化就是子串的pos值(j)了。通过分析发现子串中如果有相等字符,j值的变化就会不相同,也就是说,这个 阅读全文

posted @ 2018-02-26 09:43 AlanTu 阅读(280) 评论(0) 推荐(0)

字符串 - 基本操作

摘要: 字符串(string)是由0个或多个字符组成的有限序列。一般使用顺序存储结构,末尾以'\0'表示结束,但不计入字符串的长度。 示例程序:(改编自《大话数据结构》) C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 阅读全文

posted @ 2018-02-26 09:41 AlanTu 阅读(504) 评论(0) 推荐(0)

队列 - 链式存储结构

摘要: 队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。为了操作上的方便,我们将队头指针指向链队列的头节点,而队尾指针指向终端节点。空队列时,front和rear都指向头节点。 示例程序:(改变自《大话数据结构》) C++ Code 1 2 3 4 5 6 7 8 阅读全文

posted @ 2018-02-26 09:39 AlanTu 阅读(661) 评论(0) 推荐(0)

循环队列 - 顺序存储结构

摘要: 队列(Queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。是一种先进先出的线性表(FIFO)。允许插入的一端称为队尾,允许删除的一端称为队头。我们在《栈的顺序存储结构》中发现,栈操作的top指针在Push时增大而在Pop时减小,栈空间是可以重复利用的,而队列的front、rear 阅读全文

posted @ 2018-02-26 09:37 AlanTu 阅读(1228) 评论(0) 推荐(0)

栈 - 链式存储结构

摘要: 当单链表限定只能在头部进行插入和删除操作的时候,即为链栈,一般我们会将单链表的头指针和栈的栈顶指针top合二为一,通常对链栈来说,是不需要头节点的,因为我们维护了栈顶指针。对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间,对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是 阅读全文

posted @ 2018-02-26 09:34 AlanTu 阅读(434) 评论(0) 推荐(0)

栈 - 顺序存储结构

摘要: 栈(stack)是限定在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom) ,栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。 示例程序:(改编自《大话数据结构》) C++ Code 1 2 3 4 5 6 阅读全文

posted @ 2018-02-26 09:32 AlanTu 阅读(271) 评论(0) 推荐(0)

两栈共享存储空间

摘要: 数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度 n-1处。这样,如果两个栈增加元素,就是两端点向中间延伸。当top1 + 1 == top2 的时候为栈满。 示例代码:(改编自《大话数据结构》) C++ Code 1 2 3 4 5 阅读全文

posted @ 2018-02-26 09:32 AlanTu 阅读(441) 评论(0) 推荐(0)

静态链表

摘要: 首先我们让数组的元素都是由两个数据域组成,data和cur。也就是说,数组的每一个下标都对应一个data和一个cur。 数据域data用来存放数据元素,也就是通常我们要处理的数据;而游标cur相当于单链表中的next指针, 存放该元素的后继在数组中的下标。我们把这种用数组描述的链表叫做静态链表。 数 阅读全文

posted @ 2018-02-26 09:30 AlanTu 阅读(5695) 评论(0) 推荐(2)

线性表 - 链式存储结构

摘要: 为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai,除了存储其自身的信息之外,还需存储一个指示其 直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。N个结点链结成一个链表, 即为线性表(a1,a2,...,an)的链式存储结 阅读全文

posted @ 2018-02-26 09:29 AlanTu 阅读(264) 评论(0) 推荐(0)

线性表 - 顺序存储结构

摘要: 线性表的数据对象集合为 {a1,a2,....an},每个元素的类型均为Datatype。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。 线性表的顺序存储结构的优缺点: 优点:无须为表示表中 阅读全文

posted @ 2018-02-26 09:28 AlanTu 阅读(183) 评论(0) 推荐(0)

快速排序以及第k小元素的线性选择算法

摘要: 简要介绍下快速排序的思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。时间复杂度为O(nlogn) 一.《data structure and 阅读全文

posted @ 2018-02-26 09:27 AlanTu 阅读(1846) 评论(0) 推荐(0)

虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?

摘要: 五条基本规则: 1、如果基类已经插入了vptr, 则派生类将继承和重用该vptr。vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的。 2、在遇到通过基类指针或引用调用虚函数的语句时,首先根据指针或引用的静态类型来判断所调函数是否属 阅读全文

posted @ 2018-02-26 09:19 AlanTu 阅读(990) 评论(1) 推荐(0)

详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

摘要: 一、boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源。关于RAII的讨论可以参考前面的文章。在使用boost库之前应该先下载后放在某个路径,并在VS 包含目录中添加。下面是boost 库里面的智能 阅读全文

posted @ 2018-02-26 09:13 AlanTu 阅读(879) 评论(0) 推荐(0)

容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例

摘要: 一、容器适配器 stack queue priority_queue stack、queue、priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/deque/list对象创建了一个先进后出容器;queue是用deque或list对象创建了一个先进先 阅读全文

posted @ 2018-02-26 09:09 AlanTu 阅读(355) 评论(0) 推荐(0)

迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}

摘要: 一、迭代器适配器 反向迭代器 插入迭代器 IO流迭代器 其中反向迭代器可以参考以前的文章。 二、插入迭代器 插入迭代器实际上是一个输出迭代器(*it=; ++) back_insert_iterator back_inserter front_insert_iterator front_insert 阅读全文

posted @ 2018-02-26 09:07 AlanTu 阅读(1634) 评论(0) 推荐(0)

函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例

摘要: 一、适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈、队列和优先级队列 迭代器适配器:(反向迭代器、插入迭代器、IO流迭代器) 函数适配器:函数适配器能够将仿函数和另一个仿函数(或某个值、或某个一般函数)结合起来。 针对成员函数的函数适配器 针对一般函数的函数适 阅读全文

posted @ 2018-02-26 09:03 AlanTu 阅读(251) 评论(0) 推荐(0)

函数对象、 函数对象与容器、函数对象与算法

摘要: 一、函数对象 1、函数对象(function object)也称为仿函数(functor) 2、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。 3、任何重载了调用运算符operator()的类的对象都满足函数对象的特征 4、函数对象可以把它称之为smart function。 5、ST 阅读全文

posted @ 2018-02-26 08:57 AlanTu 阅读(340) 评论(0) 推荐(0)

剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)

摘要: 一、移除性算法 (remove) C++ Code 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 4 阅读全文

posted @ 2018-02-26 08:55 AlanTu 阅读(349) 评论(0) 推荐(0)

变动性算法源代码分析与使用示例(copy_backward、 transform、 replace_copy_if 等)

摘要: 首先回顾前面的文章,我们把for_each 归类为非变动性算法,实际上它也可以算是变动性算法,取决于传入的第三个参数,即函数 指针。如果在函数内对容器元素做了修改,那么就属于变动性算法。 变动性算法源代码分析与使用示例: 一、copy、copy_backward C++ Code 1 2 3 4 5 阅读全文

posted @ 2018-02-26 08:53 AlanTu 阅读(416) 评论(0) 推荐(0)

非变动性算法源代码分析与使用示例( for_each、min_element 、find_if、search 等)

摘要: 非变动性算法代码分析与示例: 一、for_each C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // TEMPLATE FUNCTION for_each template < class _InIt, class _Fn1 > inline _Fn1 for 阅读全文

posted @ 2018-02-26 08:51 AlanTu 阅读(323) 评论(0) 推荐(0)

迭代器类vector::iterator 和 vector::reverse_iterator 的实现、迭代器类型、常用的容器成员

摘要: 一、迭代器 迭代器是泛型指针 普通指针可以指向内存中的一个地址 迭代器可以指向容器中的一个位置 STL的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。 下面来稍微看一下vector<class>::iterator 和 v 阅读全文

posted @ 2018-02-26 08:49 AlanTu 阅读(2250) 评论(0) 推荐(0)

算法简介、7种算法分类

摘要: 一、算法 算法是以函数模板的形式实现的。常用的算法涉及到比较、交换、查找、搜索、复制、修改、移除、反转、排序、合并等等。 算法并非容器类型的成员函数,而是一些全局函数,要与迭代器一起搭配使用。 算法的优势在于只需实作一份,可以适应所有的容器,不必为每一种容器量订制。也可以与用户定义的容器搭配。 算法 阅读全文

posted @ 2018-02-26 08:49 AlanTu 阅读(4977) 评论(0) 推荐(0)

实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)

摘要: 首先,vector 在VC 2008 中的实现比较复杂,虽然vector 的声明跟VC6.0 是一致的,如下: C++ Code 1 2 template < class _Ty, class _Ax = allocator<_Ty> > class vector; 但在VC2008 中vector 阅读全文

posted @ 2018-02-26 08:47 AlanTu 阅读(825) 评论(0) 推荐(0)

STL六大组件简介

摘要: 一、STL简介 (一)、泛型程序设计 泛型编程(generic programming) 将程序写得尽可能通用 将算法从数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 (二)、什么是STL 1、STL(Standard Template Library),即标准模板库,是 阅读全文

posted @ 2018-02-26 08:44 AlanTu 阅读(1993) 评论(0) 推荐(0)

用模板实现单例模式(线程安全)、模板方式实现动态创建对象

摘要: 一、用模板实现单例模式 在前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现: 为了实现线程安全,需要在linux 下使用pthread_mutex_t 加锁,请使用g++ 编译并需要链接 -lpthread 使用的是double-check lock, 指针instance_ 最好声明为 阅读全文

posted @ 2018-02-26 08:43 AlanTu 阅读(1019) 评论(0) 推荐(0)

缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename

摘要: 一、缺省模板参数 回顾前面的文章,都是自己管理stack的内存,无论是链栈还是数组栈,能否借助标准模板容器管理呢?答案是肯定的,只需要多传一个模板参数即可,而且模板参数还可以是缺省的,如下: template <typename T, typename CONT = std::deque<T> > 阅读全文

posted @ 2018-02-26 08:42 AlanTu 阅读(368) 评论(0) 推荐(0)

导航