zoukankan      html  css  js  c++  java
  • FastDFS分布式文件系统

      一,FastDFS介绍

      1,简介

      FastDFS 是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。

    FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)。

      Tracker Server:跟踪服务器,主要做调度工作,起到均衡的作用;负责管理所有的 storage server和 group,每个 storage 在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。

      Storage Server:存储服务器,主要提供容量和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份。

      Client:客户端,上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。

      2,FastDFS的存储策略

      为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。

    在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。

      3,FastDFS的上传过程

      FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。

    Storage Server会定期的向Tracker Server发送自己的存储信息。当Tracker Server Cluster中的Tracker Server不止一个时,各个Tracker之间的关系是对等的,所以客户端上传时可以选择任意一个Tracker。

    当Tracker收到客户端上传文件的请求时,会为该文件分配一个可以存储文件的group,当选定了group后就要决定给客户端分配group中的哪一个storage server。当分配好storage server后,客户端向storage发送写文件请求,storage将会为文件分配一个数据存储目录。然后为文件分配一个fileid,最后根据以上的信息生成文件名存储文件。

      4,FastDFS的文件同步

      写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。

    每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。

    storage的同步进度会作为元数据的一部分汇报到tracker上,tracke在选择读storage的时候会以同步进度作为参考。

      5,FastDFS文件下载

      客户端uploadfile成功后,会拿到一个storage生成的文件名,接下来客户端根据这个文件名即可访问到该文件。

      跟upload file一样,在downloadfile时客户端可以选择任意tracker server。tracker发送download请求给某个tracker,必须带上文件名信息,tracke从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读请求。

      二,安装FastDFS

      安装环境查看

      主机规划

    主机名:fastdfs-tracker IP:192.168.56.11 
    主机名:fastdfs-storage IP:192.168.56.12 
    

      修改/eth/hosts

    192.168.56.11 fastdfs.com
    

      1,下载安装libfastcommon

      libfastcommon是从 FastDFS 和 FastDHT 中提取出来的公共 C 函数库,基础环境,安装即可 。

      下载,两台主机都执行相同的安装步骤

    wget https://github.com/happyfish100/libfastcommon/archive/V1.0.7.tar.gz
    

      安装

    tar -xf V1.0.7.tar.gz 
    cd libfastcommon-1.0.7/
    ./make.sh 
    yum -y install gcc-c++
    ./make.sh 
    ./make.sh install
    

      libfastcommon.so 安装到了/usr/lib64/libfastcommon.so,但是FastDFS主程序设置的lib目录是/usr/local/lib,所以需要创建软链接

      下载安装FastDFS

    wget https://github.com/happyfish100/fastdfs/archive/V5.05.tar.gz
    tar -xf V5.05.tar.gz 
    cd fastdfs-5.05/
    ./make.sh && ./make.sh  install
    

      安装完成后的启动脚本

    /etc/init.d/fdfs_storaged
    /etc/init.d/fdfs_trackerd
    

      默认配置文件

      命令工具在/usr/bin

      FastDFS脚本服务设置的bin目录是/usr/local/bin但是实际安装在/usr/bin下设置软连接

    ln -s /usr/bin/fdfs_trackerd /usr/local/bin/
    ln -s /usr/bin/fdfs_storaged /usr/local/bin/
    ln -s /usr/bin/stop.sh /usr/local/bin/
    ln -s /usr/bin/restart.sh /usr/local/bin/
    

      配置FastDFS跟踪器(Tracker)

    cd /etc/fdfs/
    cp tracker.conf.sample tracker.conf
    vim tracker.conf
    

      编辑配置文档

    #配置文件是否不生效,false为生效
    disabled=false
    #配置IP也可以为代表所有
    bind_addr=192.168.56.11
    #监听端口
    port=22122
    connect_timeout=90
    network_timeout=90
    base_path=/opt/fdfsdata/tracker
    max_connections=256
    accept_threads=4
    work_threads=4
    store_lookup=2
    #store_group=group1
    store_group=0
    store_server=0
    store_path=0
    download_server=0
    reserved_storage_space = 10%
    log_level=info
    run_by_group=
    run_by_user=
    allow_hosts=*
    sync_log_buff_interval = 10
    check_active_interval = 120
    thread_stack_size = 64KB
    storage_ip_changed_auto_adjust = true
    storage_sync_file_max_delay = 86400
    storage_sync_file_max_time = 300
    use_trunk_file = false 
    slot_min_size = 256
    slot_max_size = 16MB
    trunk_file_size = 64MB
    trunk_create_file_advance = false
    trunk_create_file_time_base = 02:00
    trunk_create_file_interval = 86400
    trunk_create_file_space_threshold = 20G
    trunk_init_check_occupying = false
    trunk_init_reload_from_binlog = false
    trunk_compress_binlog_min_interval = 0
    use_storage_id = false
    storage_ids_filename = storage_ids.conf
    id_type_in_filename = ip
    store_slave_file_use_link = false
    rotate_error_log = false
    error_log_rotate_time=00:00
    rotate_error_log_size = 0
    log_file_keep_days = 0
    use_connection_pool = false
    connection_pool_max_idle_time = 3600
    #配置http服务端口
    http.server_port=80
    http.check_alive_interval=90
    http.check_alive_type=tcp
    http.check_alive_uri=/status.html
    

      创建tracker基础数据目录,即base_path对应的目录

    mkdir -p /opt/fdfsdata/tracker
    

      防火墙开启对应端口,这里我们把防火墙关闭

      启动tracker

      初次成功启动,会在 /ljzsg/fdfsdfs/tracker/ (配置的base_path)下创建 data、logs 两个目录

     /etc/init.d/fdfs_trackerd start
    #也可以使用一下方式启动,前提是设置了软连接
    systemctl start fdfs_trackerd
    

      tracker server目录及文件结构

    .
    └── tracker
        ├── data
        │?? ├── fdfs_trackerd.pid     #存储分组信息
        │?? └── storage_changelog.dat #存储服务器列表
        └── logs
            └── trackerd.log         #tracker server日志文件
    

      配置FastDFS存储(storage)在192.168.56.12上

    cd /etc/fdfs/
    cp storage.conf.sample storage.conf
    vim storage.conf
    

      编辑配置文档

    #配置是否不生效,这里生效
    disabled=false
    #组名
    group_name=group1
    bind_addr=192.168.56.12
    client_bind=true
    #服务端口
    port=23000
    connect_timeout=90
    network_timeout=90
    heart_beat_interval=90
    stat_report_interval=60
    #Storage数据日志目录地址(跟目录必须存在,子目录会自动生成)
    base_path=/opt/fdfsdata/storage
    max_connections=256
    buff_size = 256KB
    accept_threads=1
    work_threads=4
    disk_rw_separated = true
    disk_reader_threads = 1
    disk_writer_threads = 1
    sync_wait_msec=50
    sync_interval=0
    # 允许系统同步的时间段 (默认是全天) 。一般用于避免高峰同步产生一些问题而设定
    sync_start_time=00:00
    sync_end_time=23:59
    write_mark_file_freq=500
    #存放文件时 storage server 支持多个路径。这里配置存放文件的基路径数目,通常只配一个目录。
    store_path_count=1
    #逐一配置 store_path_count 个路径,索引号基于 0
    #如果不配置 store_path0,那它就和 base_path 对应的路径一样。
    store_path0=/opt/fdfsdata/storage
    # FastDFS 存储文件时,采用了两级目录。这里配置存放文件的目录个数。 
    # 如果本参数只为 N(如: 256),那么 storage server 在初次运行时,会在 store_path 下自动创建 N * N 个存放文件的子目录。
    subdir_count_per_path=256
    # tracker_server 的列表 ,会主动连接 tracker_server
    # 有多个 tracker server 时,每个 tracker server 写一行
    tracker_server=fastdfs.com:22122
    log_level=info
    run_by_group=
    run_by_user=
    allow_hosts=*
    file_distribute_path_mode=0
    file_distribute_rotate_count=100
    fsync_after_written_bytes=0
    sync_log_buff_interval=10
    sync_binlog_buff_interval=10
    sync_stat_file_interval=300
    thread_stack_size=512KB
    upload_priority=10
    if_alias_prefix=
    check_file_duplicate=0
    file_signature_method=hash
    key_namespace=FastDFS
    keep_alive=0
    use_access_log = false
    rotate_access_log = false
    access_log_rotate_time=00:00
    rotate_error_log = false
    error_log_rotate_time=00:00
    rotate_access_log_size = 0
    rotate_error_log_size = 0
    log_file_keep_days = 0
    file_sync_skip_invalid_record=false
    use_connection_pool = false
    connection_pool_max_idle_time = 3600
    http.domain_name=
    #访问端口
    http.server_port=80
    

      创建storage基础数据目录,对应base_path目录

    mkdir /opt/fdfsdata/storage -p
    

      启动

    etc/init.d/fdfs_storaged start
    

      以后已这种方式启动

    systemctl status fdfs_storaged
    

      查看是否已启动

      查看storage和tracker是否在通信

     

      同tracker storage启动成功后在base_path下创建了data,logs目录记录storage server信息

      在store_path0目录(这里同base_path目录)下创建了N*N个子目录

      

      文件上传测试

      修改tracker服务器中的客户端配置文件

    cd /etc/fdfs/
    cp client.conf.sample client.conf
    vim client.conf
    

      

    connect_timeout=30
    network_timeout=60
    #client的数据和日志记录
    base_path=/opt/fastdfsdata/client
    #tracker端口
    tracker_server=fastdfs.com:22122
    log_level=info
    use_connection_pool = false
    connection_pool_max_idle_time = 3600
    load_fdfs_parameters_from_tracker=false
    use_storage_id = false
    storage_ids_filename = storage_ids.conf
    http.tracker_server_port=80
    

      上传测试

     /usr/bin/fdfs_upload_file /etc/fdfs/client.conf namei.jpeg
    

      返回的文件ID由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。

       PS:以上上传为默认的端口23000如果配置了多个storage,需要上传到不同的storage需要在上传的时候指定对应storage的端口

     /usr/bin/fdfs_upload_file /etc/fdfs/client.conf test.txt 192.168.56.11:23001
    

      

       三,安装Nginx

      上面将文件上传成功了,但我们无法下载。因此安装Nginx作为服务器以支持Http方式访问文件。同时,后面安装FastDFS的Nginx模块也需要Nginx环境。

    Nginx只需要安装到StorageServer所在的服务器即可,用于访问文件。我这里由于是单机,TrackerServer和StorageServer在一台服务器上。

    yum -y install gcc-c++ pcre pcre-devel
    yum -y install gcc-c++ pcre pcre-devel zlib zlib-devel
    wget -c https://nginx.org/download/nginx-1.12.1.tar.gz
    tar -xf nginx-1.12.1.tar.gz 
    cd nginx-1.12.1
    ./configure --prefix=/usr/local/nginx
    make && make install
    

      修改配置文件添加一下内容

    location /group1/M00 {
        alias /opt/fdfsdata/storage/data/;
    }

      重启nginx

    /usr/local/nginx/sbin/nginx -s reload
    

      访问测试

    http://192.168.56.12/group1/M00/00/00/wKg4DFwsjoKAXmKhAACwm4S3uBc21.jpeg
    

      

      四,FastDFS配置Nginx模块

      fastdfs-nginx-module模块说明

      FastDFS 通过 Tracker 服务器,将文件放在 Storage 服务器存储, 但是同组存储服务器之间需要进行文件复制, 有同步延迟的问题。

      假设 Tracker 服务器将文件上传到了 192.168.51.128,上传成功后文件 ID已经返回给客户端。

      此时 FastDFS 存储集群机制会将这个文件同步到同组存储 192.168.51.129,在文件还没有复制完成的情况下,客户端如果用这个文件 ID 在 192.168.51.129 上取文件,就会出现文件无法访问的错误。

      而 fastdfs-nginx-module 可以重定向文件链接到源服务器取文件,避免客户端由于复制延迟导致的文件无法访问错误。

      下载fastdfs-nginx-module解压

    wget https://github.com/happyfish100/fastdfs-nginx-module/archive/5e5f3566bbfa57418b5506aaefbe107a42c9fcb1.zip
    unzip 5e5f3566bbfa57418b5506aaefbe107a42c9fcb1.zip
    

      重新编译nginx

    cd nginx-1.12.1
    ./configure --prefix=/usr/local/nginx/ --add-module=/nas/softs/fastdfs/fastdfs-nginx-module/src/
    make && make install
    

      复制 fastdfs-nginx-module 源码中的配置文件到/etc/fdfs 目录, 并修改

    cd /nas/softs/fastdfs/fastdfs-nginx-module/src
    cp mod_fastdfs.conf /etc/fdfs/
    

      修改配置

    #连接超时
    connect_timeout=10
    network_timeout=30
    base_path=/tmp
    load_fdfs_parameters_from_tracker=true
    storage_sync_file_max_delay = 86400
    use_storage_id = false
    storage_ids_filename = storage_ids.conf
    #设置tracker服务器
    tracker_server=192.168.56.11:22122
    #设置storage端口
    storage_server_port=23000
    group_name=group1
    #如果文件ID的uri中包含/group**,则要设置为true
    url_have_group_name = true
    store_path_count=1
    #Storage 配置的store_path0路径,必须和storage.conf中的一致
    store_path0=/opt/fdfsdata/storage
    log_level=info
    log_filename=
    response_mode=proxy
    if_alias_prefix=
    flv_support = true
    flv_extension = flv
    group_count = 0
    

      复制FastDFS部分配置文件到/etc/fdfs目录

    cd /nas/softs/fastdfs/fastdfs-5.05/conf/
    cp anti-steal.jpg http.conf mime.types /etc/fdfs/
    

      修改nginx配置文件添加模块

    location ~/group([0-9])/M00 {
        alias /opt/fdfsdata/storage/data/;
        ngx_fastdfs_module;
    }
    

      

      注意:

      listen 80 端口值是要与 /etc/fdfs/storage.conf 中的 http.server_port=80 (前面改成80了)相对应。如果改成其它端口,则需要统一,同时在防火墙中打开该端口。

      location 的配置,如果有多个group则配置location ~/group([0-9])/M00 ,没有则不用配group。

      启动nginx出现以下代表配置成功

      在地址栏访问

    http://192.168.56.12/group1/M00/00/00/wKg4DFwsjoKAXmKhAACwm4S3uBc21.jpeg

      能下载文件就算安装成功。注意和第三点中直接使用nginx路由访问不同的是,这里配置 fastdfs-nginx-module 模块,可以重定向文件链接到源服务器取文件。

      设置多个storage

      在实际工作中往往需要多个storage下面配置生成secret和public两个storage

      secret的fdfs配置

    cat /etc/fdfs/secret.conf
    
    disabled=false
    group_name=secret
    bind_addr=
    client_bind=true
    port=23001
    connect_timeout=90
    network_timeout=90
    heart_beat_interval=90
    stat_report_interval=60
    base_path=/opt/fastdfsdata/secret
    max_connections=256
    buff_size = 256KB
    accept_threads=1
    work_threads=4
    disk_rw_separated = true
    disk_reader_threads = 1
    disk_writer_threads = 1
    sync_wait_msec=50
    sync_interval=0
    sync_start_time=00:00
    sync_end_time=23:59
    write_mark_file_freq=500
    store_path_count=1
    store_path0=/opt/fastdfsdata/secret
    subdir_count_per_path=256
    tracker_server=192.168.1.227:22122
    log_level=info
    run_by_group=
    run_by_user=
    allow_hosts=*
    file_distribute_path_mode=0
    file_distribute_rotate_count=100
    fsync_after_written_bytes=0
    sync_log_buff_interval=10
    sync_binlog_buff_interval=10
    sync_stat_file_interval=300
    thread_stack_size=512KB
    upload_priority=10
    if_alias_prefix=
    check_file_duplicate=0
    file_signature_method=hash
    key_namespace=FastDFS
    keep_alive=0
    use_access_log = false
    rotate_access_log = false
    access_log_rotate_time=00:00
    rotate_error_log = false
    error_log_rotate_time=00:00
    rotate_access_log_size = 0
    rotate_error_log_size = 0
    log_file_keep_days = 0
    file_sync_skip_invalid_record=false
    use_connection_pool = false
    connection_pool_max_idle_time = 3600
    http.domain_name=
    http.server_port=8081
    

       public的fdfs配置

    disabled=false
    group_name=public
    bind_addr=
    client_bind=true
    port=23002
    connect_timeout=90
    network_timeout=90
    heart_beat_interval=90
    stat_report_interval=60
    base_path=/opt/fastdfsdata/public
    max_connections=256
    buff_size = 256KB
    accept_threads=1
    work_threads=4
    disk_rw_separated = true
    disk_reader_threads = 1
    disk_writer_threads = 1
    sync_wait_msec=50
    sync_interval=0
    sync_start_time=00:00
    sync_end_time=23:59
    write_mark_file_freq=500
    store_path_count=1
    store_path0=/opt/fastdfsdata/public
    #store_path1=/opt/fastdfsdata/public/M01
    subdir_count_per_path=256
    tracker_server=192.168.1.227:22122
    log_level=info
    run_by_group=
    run_by_user=
    allow_hosts=*
    file_distribute_path_mode=0
    file_distribute_rotate_count=100
    fsync_after_written_bytes=0
    sync_log_buff_interval=10
    sync_binlog_buff_interval=10
    sync_stat_file_interval=300
    thread_stack_size=512KB
    upload_priority=10
    if_alias_prefix=
    check_file_duplicate=0
    file_signature_method=hash
    key_namespace=FastDFS
    keep_alive=0
    use_access_log = false
    rotate_access_log = false
    access_log_rotate_time=00:00
    rotate_error_log = false
    error_log_rotate_time=00:00
    rotate_access_log_size = 0
    rotate_error_log_size = 0
    log_file_keep_days = 0
    file_sync_skip_invalid_record=false
    use_connection_pool = false
    connection_pool_max_idle_time = 3600
    http.domain_name=
    http.server_port=8082
    

       启动

    /usr/local/bin/fdfs_storaged /etc/fdfs/public.conf
    /usr/local/bin/fdfs_storaged /etc/fdfs/secret.conf
    

       其中secret配置的http端口是8081 storage端口是23001  public配置的http端口是8082 storage端口是23002

      修改配置文件

    cat /etc/fdfs/mod_fastdfs.conf
    
    #include http.conf
    connect_timeout=2
    network_timeout=30
    storage_sync_file_max_delay = 86400
    tracker_server=192.168.1.227:22122
    load_fdfs_parameters_from_tracker=true
    log_level=info
    log_filename=/var/log/mod.log
    url_have_group_name=true
    response_mode=redirect
    if_alias_prefix=
    flv_support = true
    flv_extension = flv
    group_count = 3
    [group1]
    group_name=group1
    storage_server_port=23000
    store_path_count=1
    store_path0=/opt/fdfsdata/storage
    #base_path=/opt/fastdfsdata/fastdfs_nginx
    [group2]
    group_name=secret
    storage_server_port=23001
    store_path_count=1
    store_path0=/opt/fastdfsdata/secret
    [group3]
    group_name=public
    storage_server_port=23002
    store_path_count=1
    store_path0=/opt/fastdfsdata/public
    #store_path1=/opt/fastdfsdata/public/M01
    

       注意:如果有多个组需要配置[gropu1][group2]并且需要安装顺序配置不能跳过例如不能配置[group1]和[gropu3]如果这样配置了nginx的错误日志会报以下错误

    [2020-05-18 16:00:26] ERROR - file: /root/fastdfs-nginx-module/src//common.c, line: 103, section: group2, you must set parameter: group_name!
    2020/05/18 16:00:26 [alert] 9086#9086: worker process 9087 exited with fatal code 2 and cannot be respawned
    

       修nginx添加两个server配置

    # cat /usr/local/nginx/conf/conf.d/secret.conf 
    server {
            listen       8081;
            server_name  localhost;
            access_log  logs/host.access.log  main;
            location / {
                root   html;
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
            
            location ~/secret/M00 {
                root /opt/fastdfsdata/secret/data; 
                ngx_fastdfs_module;      
             }
        }
    
    # cat /usr/local/nginx/conf/conf.d/public.conf 
    server {
            listen       8082;
            server_name  localhost;
            access_log  logs/public.log;
            error_log  logs/public.err;
            
            location ~/public/M00 {
                root /opt/fastdfsdata/public/data; 
                ngx_fastdfs_module;  
                add_header Access-Control-Allow-Origin *;
                add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
                add_header Access-Control-Allow-Credentials: true;
                add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
                proxy_set_header X-Real-IP $remote_addr;
             }
           #location ~/public/M01 {
           #     root /opt/fastdfsdata/public/M01/data;
           #     ngx_fastdfs_module;
           #     add_header Access-Control-Allow-Origin *;
           #     add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
           #     add_header Access-Control-Allow-Credentials: true;
           #     add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
           #  }
    
        }
    

       重启nginx

      上传及访问测试,注意上传和访问的端口号

      secret

    # fdfs_upload_file /etc/fdfs/client.conf test.txt 192.168.1.228:23001
    secret/M00/00/00/wKgB5F7CRNWAKjrrAAAABelE2rQ621.txt
    [root@localhost ~]# curl 192.168.1.228:8081/secret/M00/00/00/wKgB5F7CRNWAKjrrAAAABelE2rQ621.txt
    test
    

       public

    # fdfs_upload_file /etc/fdfs/client.conf test.txt 192.168.1.228:23002
    public/M00/00/00/wKgB5F7CRQCAKSKGAAAABelE2rQ860.txt
    [root@localhost ~]# curl 192.168.1.228:8082/public/M00/00/00/wKgB5F7CRQCAKSKGAAAABelE2rQ860.txt
    test
    

       注意:如果 /etc/fdfs/mod_fastdfs.conf配置错误会导致nginx错误日志报以下错误,会导致访问nginx没有任何反应

    ERROR - file: ../common/fdfs_http_shared.c, line: 148, param "http.mime_types_filename" not exist or is empty
    2020/05/18 15:46:09 [alert] 8960#8960: worker process 8961 exited with fatal code 2 and cannot be respawned
    
  • 相关阅读:
    UVa 1394 约瑟夫问题的变形
    UVa 572 油田(DFS求连通块)
    UVa 699 下落的树叶
    Prim求解最小生成树
    UVa 839 天平
    UVa 11988 破损的键盘(链表)
    UVa 442 矩阵链乘(栈)
    UVa 二叉树的编号(二叉树)
    UVa 12100打印队列(队列)
    约瑟夫圆桌问题
  • 原文地址:https://www.cnblogs.com/minseo/p/10210428.html
Copyright © 2011-2022 走看看