Quantcast
Channel: CSDN博客推荐文章
Viewing all 35570 articles
Browse latest View live

Ubuntu 16.04 布置postfix、dovecot邮件服务器

$
0
0

一、引言

        postfixWietse VenemaIBMGPL协议之下开发的MTA(邮件传输代理)软件,也就是我们常说的SMTP服务端。postfix是Wietse Venema想要为使用最广泛的sendmail提供替代品的一个尝试。它更快、更容易管理、更安全,同时还与sendmail保持足够的兼容性。Dovecot 是一个开源的 IMAP POP3 邮件服务器,它支持多种认证方式,配置起来比较简单。使用postfix+dovecot的组合是一种很经典的邮件收发服务端解决方案。

         现代的邮件收发系统在收发邮件时一般都要求先进行验证,所谓验证就是核对用户名和密码是否正确,如下图所示的红色方框部分,就是要求我们在收发邮件时先要进行验证:


        postfix支持两种验证方式,一种是采用Dovecot的验证方式dovecot-sasl,另一种是利用cryus-sasl验证的方式,接下来我将分两篇文章分别介绍postfix设置这两种方式的方法。

二、安装和配置postfix

2.1 安装

        在终端中输入下面的命令,以安装postfix,

sudo apt-get install postfix

        在安装过程中会有界面弹出来,当显示如下所示的界面时,我们要选择Internet Site方式,然后一路确定即可。


2.2 配置

        打开/etc/postfix/main.cf文件,按照如下进行配置,其中大部分配置只是采用了postfix安装时的默认配置,对于一些特殊配置请参照下面的注释,其中需要配置服务器域名,假设当前的域名为example.cn:

myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
 
#下面这段配置中要将自己的域名加入到里面,如下加入了example.cn
mydestination = $myhostname, example.cn,localhost, localhost.localdomain, localhost
relayhost =
#加入公网的网络地址,如我的服务器公网地址是119.xxx.xxx.xxx,就在下面加入了
119.0.0.0/8这个网络地址
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104[::1]/128,119.0.0.0/8
#邮箱最大的容量,单位是字节
mailbox_size_limit = 2000000000
recipient_delimiter = +
#监听的端口设置,如果要连互联网这里一定设置成all
inet_interfaces = all
#支持的协议类型,设置成all
inet_protocols = all
#设置的邮箱目录名称,postfix采用dovecot-auth认证的话,默认系统中的用户就是邮箱的用户,当设置成如下的邮箱目录时,会在每个用户的主目录下创建一个Maildir目录用来存放邮件。
home_mailbox = Maildir/
#设置每封邮件最大的体积
message_size_limit = 20000000
#设置是否进行认证,选yes
smtpd_sasl_auth_enable = yes
#设置认证失败断开客户端
broken_sasl_auth_clients = yes
#设置认证所在的域名
smtpd_sasl_local_domain = $myhostname
#设置认证方式,这里很重要,因为要使用dovecot-auth,所以这里要填dovecot
smtpd_sasl_type = dovecot
#设置认证文件的查询路径,默认情况下Postfix的认证文件会放到/var/spool/postfix/private/auth,按照如下设置即可
queue_directory = /var/spool/postfix
smtpd_sasl_path =private/auth
#设置未认证用户不可发邮件
smtpd_sasl_security_options = noanonymous
#设置拒绝认证的黑名单,在postfix2.02之前的版本,该配置名称叫做smtpd_recipient_restrictions
smtpd_relay_restrictions=permit_mynetworks,
 permit_sasl_authenticated,
 reject_invalid_hostname,
 reject_unauth_destination
 
#下面是设置对tls的支持,在安装完之后ssl-cert-snakeoil.pem和ssl-cert-snakeoil.key这两个文件是不存在的,需要我们手动生成,稍后介绍生成方法
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database =btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database =btree:${data_directory}/smtp_scache
 

三、安装和配置dovecot

3.1 安装

        在终端输入以下命令进行安装:

sudo apt-get install doveot

3.2 配置

         找到/etc/dovecot/dovecot.conf配置文件,我们对dovecot的所有修改基本上都在这个文件之中进行:

#这里配置邮件的存放目录,这里和Postfix设置的要一致,都是在用户主目录下的Maildir目录下。
mail_location = maildir:~/Maildir
#监听所有的端口
listen= *
#允许明文密码验证
disable_plaintext_auth = no
#使用ssl加密
ssl = required
#ssl秘钥存放路径,目前这两个文件也是不存在的,也需要按照后面的步骤我们手动生成
ssl_cert =< /etc/ssl/certs/dovecot.pem
ssl_key =< /etc/ssl/private/dovecot.key
#设置认证的默认选项,auth是一个socket文件,通过该文件dovecot和postfix进行通信,来传递postfix的认证信息,这里面的path要和postfix设置的一致。
auth default { 
       socket listen {
         client {
           path =/var/spool/postfix/private/auth
           mode = 0660
           user = postfix
           group = postfix
         }
     }
}


        完成了上述设置,邮件服务端基本上就布置成功了,但是现在还是不能利用foxmail等客户端发送邮件,因为我们还有几个问题要修改

3.3 生成postfix的tsl秘钥和dovecot的ssl秘钥

        接下来我们需要利用dovecot安装包中的脚本上次上述两种秘钥。目前存放秘钥的目录/etc/ssl/certs/和/etc/ssl/ private/也是不存在的,所以需要我们先创建上述两个目录:

mkdir –p /etc/ssl/certs/
mkdir –p /etc/ssl/private /

         创建好上述的目录之后我们将利用dovecot中的脚本文件,生成ssl-cert-snakeoil.pem、ssl-cert-snakeoil.key、dovecot.pem和dovecot.key这四个文件。因为我们用apt-getinstall安装的dovecot,所以我们先要进入/ var/cache/apt/archives/这个目录下。我们用apt-getinstall        安装的所有程序的安装包都在这个目录下,找到dovecot-core***.deb安装包(后面版本号什么的省略),把它拷贝到主目录下,然后用下面的命令进行解压:

dpkg  –X  dovecot-core***.deb  dovecot/

        解压之后,在当前目录找到dovecot/usr/share/dovecot/ mkcert.sh,然后执行下面的命令:

sh mkcert.sh

        此时会在/etc/ssl/certs/目录和/etc/ssl/private/目录下生成ssl-cert-snakeoil.pem和ssl-cert-snakeoil.key两个文件,这就是我们需要的postfix的tls秘钥,我们需要的dovecot秘钥只需将上述两个文件各拷贝一份副本即可:

cp ssl-cert-snakeoil.pem  dovecot.pem
cp ssl-cert-snakeoil.key  dovecot.key

        这就完成相关秘钥的生成。

3.4 解决doveconf -n >dovecot-new.conf  等警告信息

        在完成上述布置之后,如果重启dovecot:

service dovecotrestart

        在/var/log/mail.log文件中我们会发现很多类似“Warning:doveconf-n > dovecot-new.conf”的警告信息,是因为doveconf要求我们生成新格式的配置文件,此时执行下面的命令:

doveconf -n > dovecot-new.conf

        会在当前目录下生成dovecot-new.conf文件,然后用该文件替换/var/dovecot/dovecot.conf文件。接下来重启postfix和dovecot:

service postfixrestart
service dovecotrestart

        经过了上述的步骤,已经完成了postfix和dovecot的配置,但是想要使用邮件客户端,我们还有在域名提供商那里进行域名相关的设置。

3.5 设置邮件服务器的域名解析

         在域名服务提供商那里设置域名解析,我的 example.cn 设置了5个域名解析:

         第一个是:记录类型A  主机记录mail,    指向服务器的IP地址

         第二个是:记录类型MX主机记录@指向example.cn

         第三个是:记录类型A,主机记录 www指向服务器的IP地址

         第四个是:记录类型CNAME主机记录pop.example.cn.指向 mai.example.cn

         第四个是:记录类型CNAME主机记录smtp.example.cn.指向 mai.example.cn

 

 

作者:lzhui1987 发表于2017/3/21 19:04:59 原文链接
阅读:89 评论:0 查看评论

修改postfix和dovecot的认证方式

$
0
0

一、引言

        在上一文中介绍了在Ubuntu 16.04布置postfix、dovecot邮件服务器的方法,本文紧接着上一文,主要介绍修改postfix认证方式和dovecot的认证方式。

二、修改postfix认证方式为sasl-auth

2.1 安装sasl2-bin

        想要修改postfix的认证方式为sasl-auth,需要先安装sasl2-bin,安装的方法如下:

apt-get install sasl-auth

2.2修改postfix相关配置

         我们在上一文的配置基础之上进行修改,只需要将/etc/postfix/main.cf文件中做如下修改:

2.2.1注释掉下面的配置:

#smtpd_sasl_type = dovecot
#queue_directory = /var/spool/postfix

2.2.2配置下面的语句:

smtpd_sasl_path = smtpd
smtpd_sasl_authenticated_header = yes

2.2.3在/etc/postfix/sasl/目录下创建文件smtpd.conf

内容为:

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM

2.2.4使用saslpasswd2创建用户:

saslpasswd2 -c -u test.com test
sudo cp -a /etc/sasldb2 /var/spool/postfix/etc/

        必须把数据库文件复制到postfix的运行目录下,否则会出现postfix用户无法访问该文件的权限问题,而且每次增加或者删除用户都要复制一次

2.2.5将postfix添加到sasl组:

gpasswd -a postfix sasl

2.2.6 修改sasldb权限

chmod 640 /var/spool/postfix/etc/sasldb2

2.2.7 列举sasldb2中的用户

sasldblistusers2 -f /var/spool/postfix/etc/sasldb2

        经过了上述几个步骤,就已经完成了postfix认证用户的修改,配置完后重启postfix,使用sasl-auth认证比dovecot-auth认证,效率要高很多。

三、修改dovecot的认证方式为文件认证

        dovecot默认的认证方式为系统认证,也就是说它是把每一个ubuntu系统的用户当成了email的用户,用户的名称和密码两者完全一致。下面我们就修改dovecot默认的这种认证方式。

3.1 修改10-auth.conf文件

        /etc/dovecot/conf.d/10-auth.conf文件负责设置dovecot所使用的sasl验证方法。将!include auth-system.conf.ext这行注释掉,把#includeauth-passwdfile.conf.ext这行的注释去掉,这样便可以使用密码文件来进行sasl认证。如下红色圈出部分:


3.2 创建认证文件users

        找到同一目录下auth-passwdfile.conf.ext文件中,可以看到密码文件默认为/etc/dovecot/users.接下来,需要我们创建这个文件,并填写用户信息:

       zhangsan:{plain}xxxxxxxx:1000:1000::/home/user1/zhangsan 
       lisi:{plain}xxxxxxxx:1000:1000::/home/user1/lisi

        该文件格式从左到右依次为:用户名、加密方式和口令、代收用户的用户id、代收用户的组id、邮件所在文件夹。其中邮件的所在文件夹当然是postfix所收取的邮件所在的文件夹。但是用户名是dovecot系统用户名,也就是他和postfix可以不是一一对应的。如果我们用zhangsan这个名字来收取postfix虚用户里lisi的邮件所在文件夹的邮件,也是可以的。所以MUA中可以自行设置一套收信口令。配置完成之后重启dovecot即可。

作者:lzhui1987 发表于2017/3/21 19:42:25 原文链接
阅读:86 评论:0 查看评论

《华为机试在线训练》之提取不重复的整数

$
0
0

一,题目要求

 1,题目描述:输入一个int型整数,按照从右往左的阅读顺序,返回一个不含重复数字的新的整数

 2,输入描述:输入一个int型整数

 3,输出描述:按照从右到左的阅读顺序,返回一个不含重复数字的新的整数

 4,输入例子:8976673

 5,输出例子:37689

二,思路分析

     首先可以认识到这可以利用数组来进行求解,第一反应地可以将int型整数的每一位都赋值给数组,这样数组中存放的就是对应的每一位的数字,这个时候要做的工作就是怎样去掉那些重复元素的数组元素,这个时候可以对数组进行遍历比较,如果相等则抛弃,同时将数组的长度减1,保持数组的长度,以便于输出的时候使用。

    代码如下:

#include <stdio.h>
int main()
{
    int a,n=0,b[100],count=0;

    scanf("%d", &a);
    while(a>0)
     {
         b[n] = a%10;
         a = a/10;
         n++;
         count++;
     }
    //remove_repeat(b,count);
    int i, j, k;
    for(i = 0; i < count; i ++)
    {
        for(j = i+1; j <count; j ++)//对后面每个元素比较,去重。
        {
            if(b[j] == b[i])//发现重复元素。
            {
                for(k = j+1; k<count; k ++)//依次前移一位。
                    b[k-1] = b[k];
                count--;//总长度减一。
            }
        }
    }
    for(n=0;n<count;n++)
    {
            printf("%d", b[n]);
    }

     getchar();getchar();
     return 0;
}

  结果展示为:

                               

         

作者:huangchijun11 发表于2017/3/21 20:15:37 原文链接
阅读:77 评论:0 查看评论

【PMP】PMBOK 笔记 第4章 项目整合管理

$
0
0

第4章 项目整合管理

识别、定义、组合、统一和协调各项目管理过程组的各种过程和活动而开展的过程与活动。

“整合”兼具统一、合并、沟通和集成的性质

选择资源分配方案、平衡相互竞争的目标和方案,以及管理项目管理知识领域之间的依赖关系。

当过程之间发生相互作用时,项目整合管理就显得非常必要。

在项目管理过程组的各过程间,经常反复发生联系。

图 4-1 项目整合管理概述

总结

作为本书的第一个管理过程组,贯穿了整个项目。

其中涉及到了很多内容,都是在其他章节才有的,所以只要了解就行,以后多看几遍书,知识点就会交叉补充的。

4.1 制定项目章程

正式批准项目并授权项目经理在项目活动中使用组织资源

作用: 明确定义项目开始和项目边界,确立项目的正式地位,高级管理层直述他们对项目的支持

图 4-2 制定项目章程:输入、工具与技术和输出

图 4-3 制定项目章程的数据流向图

项目章程在项目执行组织与需求组织之间建立起伙伴关系。

在执行外部项目时,通常需要一份正式的合同来确立这种协作关系。

经批准的项目章程意味着项目的正式启动。在项目中,应尽早确认并任命项目经理,最好在制定项目章程时就任命,最晚也必须在规划开始之前。项目章程应该由发起项目的实体批准。

项目由项目以外的实体来启动.项目启动者或发起人应该具有一定的职权,能为项目获取资金并提供资源。

不要把项目章程看做合同,因为其中未承诺报酬或金钱或用于交换的对价。

4.1.1 制定项目章程:输入

4.1.1.1 项目工作说明书

项目工作说明书(Statement of Work,SOW)是对项目需交付的产品、服务或成果的叙述性说明。

对于外部项目,工作说明书则由客户提供,可以是招标文件(如建议邀请书、信息邀请书、投标邀请书)的一部分,或合同的一部分。

SOW包括以下内容:

  • 业务需要
  • 产品范围描述
  • 战略计划

4.1.1.2 商业论证

商业论证或类似文件能从商业角度提供必要的信息,决定项目是否值得投资。

项目经理负责确保项目有效地满足在商业论证中规定的组织目的和广大干系人的需求

4.1.1.3 协议

协议定义了启动项目的初衷。

通常,为外部客户做项目时,就用合同。

4.1.1.4 事业环境因素

见2.1.5节。

  • 政府标准、行业标准或法规
  • 组织文化和结构
  • 市场条件

4.1.1.5 组织过程资产

见2.1.4节。

  • 组织的标准过程、政策和过程定义
  • 模板(如项目章程模板)
  • 历史信息与经验教训知识库(如项目记录和文件、完整的项目收尾信息和文档、关于以往项目选择决策的结果和以往项目绩效的信息,以及风险管理活动中产生的信息)

4.1.2 制定项目章程:工具和技术

4.1.2.1 专家判断

专家判断可来自具有专业知识或受过专业培训的任何小组或个人,可从许多渠道获取。

包括

  • 组织内的其他部门
  • 顾问
  • 干系人,包括客户或发起人
  • 专业与技术协会
  • 行业团体
  • 主题专家(SME)
  • 项目管理办公室(PMO)

4.1.2.2 引导技术

头脑风暴、冲突处理、问题解决和会议管理

4.1.3 制定项目章程:输出

4.1.3.1 项目章程

在项目章程中记录业务需要、假设条件、制约因素、对客户需要和高层级需求的理解,以及需要交付的新产品、服务或成果

  • 项目目的或批准项目的原因
  • 可测量的项目目标和相关的成功标准
  • 高层级需求
  • 假设条件和制约因素
  • 高层级项目描述和边界定义
  • 高层级风险
  • 总体里程碑进度计划
  • 总体预算
  • 干系人清单
  • 项目审批要求
  • 委派的项目经理及其权责
  • 发起人或其他批准项目章程的人员的姓名和职权

4.2 制定项目管理计划

生成一份核心文件,作为所有项目工作的依据

图 4-4 制定项目管理计划:输入、工具与技术和输出

图 4-5 制定项目管理计划的数据流向图

该计划需要通过不断更新来渐进明细。

这些更新需要由实施整体变更控制过程(见 4.5 节)进行控制和批准。

4.2.1 制定项目管理计划:输入

4.2.1.1 项目章程

见 4.1.3.1 节。

项目章程至少应该定义项目的高层级边界。

4.2.1.2 其他过程的输出

编制项目管理计划需要整合诸多过程(如第 5 章至第 13 章所述)的输出。其他规划过程所输出的任何基准和子管理计划,都是本过程的输入。

4.2.1.3 事业环境因素

见 2.1.5 节。

  • 政府或行业标准
  • 纵向市场(如建筑)或专门领域(如环境、安全、风险或敏捷软件开发)的项目管理知识体系
  • 项目管理信息系统(如自动化工具,包括进度计划软件、配置管理系统、信息收集与发布系统,或进入其他在线自动化系统的网络界面)
  • 组织的结构、文化、管理实践和可持续发展
  • 基础设施(如现有设施和固定资产)
  • 人事管理制度(如人员招聘和解雇指南、员工绩效评价、员工发展与培训记录)

4.2.1.4 组织过程资产

见 2.1.4 节。

主要包括

  • 配置管理知识库,包括组织标准、政策、程序和项目文件的各种版本与基准

4.2.2 制定项目管理计划:工具与技术

4.2.2.1 专家判断

主要为

  • 根据项目需要而裁剪项目管理过程

4.2.2.2 引导技术

见 4.1.2.2 节。

4.2.3 制定项目管理计划:输出

4.2.3.1 项目管理计划

项目基准包括

  • 范围基准(见 5.4.3.1 节)
  • 进度基准(见 6.6.3.1 节)
  • 成本基准(见 7.3.3.1 节)

子管理计划包括

  • 范围管理计划(见 5.1.3.1 节)
  • 需求管理计划(见 5.1.3.2 节)
  • 进度管理计划(见 6.1.3.1 节)
  • 成本管理计划(见 7.1.3.1 节)
  • 质量管理计划(见 8.1.3.1 节)
  • 过程改进计划(见 8.1.3.2 节)
  • 人力资源管理计划(见 9.1.3.1 节)
  • 沟通管理计划(见 10.1.3.1 节)
  • 风险管理计划(见 11.1.3.1 节)
  • 采购管理计划(见 12.1.3.1 节)
  • 干系人管理计划(见 13.2.3.1 节)

项目管理计划可以是概括或详细的。

项目管理计划一旦被确定为基准,就只有在提出变更请求并经实施整体变更控制过程批准后,才能变更。

项目管理计划是用于管理项目的主要文件之一。

表 4-1 项目管理计划与项目文件的区别

4.3 指导与管理项目工作

图 4-6 指导与管理项目工作:输入、工具与技术和输出

图 4-7 指导与管理项目工作的数据流向图

指导与管理项目工作:

  • 纠正措施
  • 预防措施
  • 缺陷补救

4.3.1 指导与管理项目工作:输入

4.3.1.1 项目管理计划

见 4.2.3.1 节。

包括

  • 范围管理计划(见 5.1.3.1 节)
  • 需求管理计划(见 5.1.3.2 节)
  • 进度管理计划(见 6.1.3.1 节)
  • 成本管理计划(见 7.1.3.1 节)
  • 干系人管理计划(见 13.2.3.1 节)

4.3.1.2 批准的变更请求

批准的变更请求是实施整体变更控制过程的输出,包括那些经变更控制委员会审查和批准的变更请求。

批准的变更请求可能是纠正措施、预防措施或缺陷补救。

4.3.1.3 事业环境因素

见 2.1.5 节。

主要包括

  • 项目管理信息系统(如自动化工具,包括进度计划软件)

4.3.1.4 组织过程资产

见 2.1.4 节。

4.3.2 指导与管理项目工作:工具与技术

4.3.2.1 专家判断

4.3.2.2 项目管理信息系统

项目管理信息系统提供下列工具:进度计划工具、工作授权系统、配置管理系统、信息收集与发布系统,或进入其他在线自动化系统的网络界面。也可用于自动收集和报告关键绩效指标(KPI)。

4.3.2.3 会议

会前,应该做好准备工作,包括确定会议议程、目的、目标和期限;会后,要形成书面的会议纪要和行动方案。

4.3.3 指导与管理项目工作:输出

4.3.3.1 可交付成果

可交付成果是在某一过程、阶段或项目完成时,必须产出的任何独特并可核实的产品、成果或服务能力。
可交付成果通常是为实现项目目标而完成的有形的组件

4.3.3.2 工作绩效数据

活动中收集到的原始观察结果和测量值。

数据是指最低层的细节,将由其他过程从中提炼出项目信息。

4.3.3.3 变更请求

变更请求是关于修改任何文档、可交付成果或基准的正式提议。

变更请求可以是直接或间接的,可以由外部或内部提出,可能是自选或由法律/合同所强制的。

  • 纠正措施
  • 预防措施
  • 缺陷补救
  • 更新

4.3.3.4 项目管理计划更新

  • 范围管理计划
  • 需求管理计划
  • 进度管理计划
  • 成本管理计划
  • 质量管理计划
  • 过程改进计划
  • 人力资源管理计划
  • 沟通管理计划
  • 风险管理计划
  • 采购管理计划
  • 干系人管理计划
  • 项目基准

4.3.3.5 项目文件更新

  • 需求文件
  • 项目日志(用于记录问题、假设条件等)
  • 风险登记册
  • 干系人登记册

4.4 监控项目工作

本过程的主要作用是,让干系人了解项目的当前状态、已采取的步骤,以及对预算、进度和范围的预测。

图 4-8 监控项目工作:输入、工具与技术和输出

图 4-9 监控项目工作的数据流向图

监督是贯穿于整个项目的项目管理活动之一

4.4.1 监控项目工作:输入

4.4.1.1 项目管理计划

见 4.2.3.1 节。

子计划和基准包括

  • 范围管理计划(见 5.1.3.1 节)
  • 需求管理计划(见 5.1.3.2 节)
  • 进度管理计划(见 6.1.3.1 节)
  • 成本管理计划(见 7.1.3.1 节)
  • 质量管理计划(见 8.1.3.1 节)
  • 过程改进计划(见 8.1.3.2 节)
  • 人力资源管理计划(见 9.1.3.1 节)
  • 沟通管理计划(见 10.1.3.1 节)
  • 风险管理计划(见 11.1.3.1 节)
  • 采购管理计划(见 12.1.3.1 节)
  • 干系人管理计划(见 13.2.3.1 节)
  • 范围基准(见 5.4.3.1 节)
  • 进度基准(见 6.6.3.1 节)
  • 成本基准(见 7.3.3.1 节)

4.4.1.2 进度预测

见 6.7.3.2.节。

基于实际进展与进度基准的比较而计算出进度预测,即完工尚需时间估算(ETC),通常表示为进度偏差(SV)进度绩效指数(SPI)

4.4.1.3 成本预测

见 7.4.3.2 节。

基于实际进展与成本基准的比较而计算出的完工尚需估算(ETC),通常表示为成本偏差(CV)成本绩效指数(CPI)。通过比较完工估算(EAC)完工预算(BAC),可以看出项目是否仍处于可容忍范围内,是否需要提出变更请求。

4.4.1.4 确认的变更

见 8.3.3.2 节。

4.4.1.5 工作绩效信息

工作绩效数据就转化为工作绩效信息。

4.4.1.6 事业环境因素

见 2.1.5.节。

4.4.1.7 组织过程资产

见 2.1.4.节。

4.4.2 监控项目工作:工具与技术

4.4.2.1 专家判断

4.4.2.2 分析技术

分析技术来预测潜在的后果。

  • 根本原因分析
  • 故障树分析(FTA)
  • 储备分析
  • 挣值管理

4.4.2.3 项目管理信息系统

4.4.2.4 会议

见 4.3.2.3 节。

会议可以是面对面或虚拟会议,正式或非正式会议。

4.4.3 监控项目工作:输出

4.4.3.1 变更请求

变更请求可能导致需要收集和记录新的需求。

4.4.3.2 工作绩效报告

工作绩效报告是为制定决策、采取行动或引起关注而汇编工作绩效信息所形成的实物或电子项目文件

4.4.3.3 项目管理计划更新

  • 范围管理计划(见 5.1.3.1 节)
  • 需求管理计划(见 5.1.3.2 节)
  • 进度管理计划(见 6.1.3.1 节)
  • 成本管理计划(见 7.1.3.1 节)
  • 质量管理计划(见 8.1.3.1 节)
  • 范围基准(见 5.4.3.1 节)
  • 进度基准(见 6.6.3.1 节)
  • 成本基准(见 7.3.3.1 节)

4.4.3.4 项目文件更新

  • 进度和成本预测
  • 工作绩效报告
  • 问题日志

4.5 实施整体变更控制

实施整体变更控制是审查所有变更请求,批准变更,管理对可交付成果、组织过程资产、项目文件和项目管理计划的变更,并对变更处理结果进行沟通的过程。

图 4-10 实施整体变更控制:输入、工具与技术和输出

图 4-11 实施整体变更控制的数据流向图

实施整体变更控制过程贯穿项目始终,项目经理对此负最终责任。

来确保只有经批准的变更才能纳入修改后的基准中。

项目的任何干系人都可以提出变更请求。尽管也可以口头提出,但所有变更请求都必须以书面形式记录。

变更请求应该由变更控制系统和配置控制系统中规定的过程进行处理。应该评估变更对时间和成本的影响,并向这些过程提供评估结果。

每项记录在案的变更请求都必须由一位责任人批准或否决,这个责任人通常是项目发起人或项目经理。

应该由变更控制委员会(CCB)来开展实施整体变更控制过程。CCB 是一个正式组成的团体,负责审查、
评价、批准、推迟或否决项目变更,以及记录和传达变更处理决定。

在 CCB 批准之后,还可能需要得到客户或发起人的批准,除非他们本来就是 CCB的成员。

配置控制重点关注可交付成果及各个过程的技术规范。

分配置管理活动:

  • 配置识别
  • 配置状态记录。为了能及时提供关于配置项的适当数据,应记录和报告相关信息。
  • 配置核实与审计

4.5.1 实施整体变更控制:输入

4.5.1.1 项目管理计划

见 4.2.3.1 节。

4.5.1.2 工作绩效报告

见 4.4.3.2 节。

4.5.1.3 变更请求

所有监控过程及很多执行过程都会输出“变更请求”。

纠正和预防措施通常不会影响项目基准,而只影响相对于基准的项目绩效。

4.5.1.4 事业环境因素

见 2.1.5 节。

4.5.1.5 组织过程资产

见 2.1.4 节。

4.5.2 实施整体变更控制:工具与技术

4.5.2.1 专家判断

4.5.2.2 会议

CCB 的决定都应记录在案,并向干系人传达,以便其知晓并采取后续措施。

4.5.2.3 变更控制工具

4.5.3 实施整体变更控制:输出

4.5.3.1 批准的变更请求

全部变更请求的处理结果,无论批准与否,都要在变更日志中更新。这种更新是项目文件更新的一部分。

4.5.3.2 变更日志

变更日志用来记录项目过程中出现的变更。

被否决的变更请求也应该记录在变更日志中。

4.5.3.3 项目管理计划更新

4.5.3.4 项目文件更新

4.6 结束项目或阶段

总结经验教训 , 开展新工作而释放组织资源。

图 4-12 结束项目或阶段:输入、工具与技术和输出

图 4-13 结束项目或阶段的数据流向图

项目经理需要审查范围基准,确保在项目工作全部完成后才宣布项目结束。如果项目在完工前就提前终止,结束项目或阶段过程还需要制定程序,来调查和记录提前终止的原因。

4.6.1 结束项目或阶段:输入

4.6.1.1 项目管理计划

见 4.2.3.1 节。

项目经理和项目发起人之间的协议,其中规定了项目完工的标准。

4.6.1.2 验收的可交付成果

见 5.5 节。

验收的可交付成果可能包括批准的产品规范、交货收据和工作绩效文件。

4.6.1.3 组织过程资产

见 2.1.4 节。

4.6.2 结束项目或阶段:工具与技术

4.6.2.1 专家判断

由相关专家确保项目或阶段收尾符合适用标准。

4.6.2.2 分析技术

见 4.4.2.2 节。

4.6.2.3 会议

见 4.3.2.3 节。

4.6.3 结束项目或阶段:输出

4.6.3.1 最终产品、服务或成果移交

4.6.3.2 组织过程资产更新

  • 项目档案。在项目活动中产生的各种文件
  • 项目或阶段收尾文件。如果项目在完工前提前终止,则需要在正式的收尾文件中说明项目终止的原因,并规定正式程序,把该项目的已完成和未完成的可交付成果移交他人。
  • 历史信息
作者:diandianxiyu 发表于2017/3/21 20:17:17 原文链接
阅读:206 评论:0 查看评论

Ext常用组件

$
0
0

表单是客户端和服务器交互的一种重要方式,Ext表单控件在界面体验效果的美观度及功能的全面性上都有着首屈一指的影响力,表面上,表单控件只是添加了一些 CSS样式,但它在数据校验方面非常灵活。

实际上,Ext提供的功能远不止这些,它还可以使不同的消息对话框更加美观、容易配置、拖动等,这都是传统的页面方式无法比拟的。

此外,Ext的树形结构是Ext框架的重要组成部分,可以动态添加、删除或修改节点,实现拖拽和右键菜单等功能,而且其界面和动画十分美观。本章将分别从Ext的消息对话框、表单控件以及Ext树形结构开始,详细讲解Ext常用控件。 

 

核心技能部分

1.1 Ext消息对话框

传统方法 alert、confirm等)产生的对话框非常呆板,对界面的体验效果产生了负面影响。ExtJS 提供了一套非常漂亮的对话框,可以实现华丽的应用程序界面。

1.1.1 Ext.MessageBox介绍

Ext中的 MessageBox是一种特殊的窗口,配置简单,可以任意拖动、摆放,也可以实现对任何控件的使用。Ext.MessageBox 是一个用于产生不同风格提示框的实体类,它的另一种写法是 Ext.Msg。与传统浏览器的 alert 提示不同,Ext.MessageBox是异步的,在显示一个 Ext.MessageBox时并不会停止代码的运行。因此,代码需要获得用户反馈后再运行时,必须使用回调函数。Ext.MessageBox为程序员提供了弹出提示框的简单方法,使用它提供的 alert、confirm、prompt等对话框完全可以替代传统的同类对话框。此外,Ext.MessageBox还提供了进度条等功能。

1.1.2 Ext. MessageBox. alert()

Ext.MessageBox.alert()一般包含 title、msg 和 function 这 3 个参数。其中,title 指窗口的标题,msg 指窗口的内容,function 指点击关闭按钮后执行的函数。

 

Alert(title,msg,function(){} )

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

 

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

 

</head>

 

<body>

 

<h1>消息对话框</h1>

<p>=======================</p>

<p>确认对话框</p>

<p><button id="messageBox1">Click Me</button></p>

<script language="javascript">

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(){

Ext.MessageBox.alert('状态','保存成功');

});

});

</script>

</body>

</html>

示例 3.1 实现了一个简单的 alert对话框

 


1.1.3 Ext. MessageBox. confirm()

Ext.MessageBox.confirm()方法基本上与 alert()方法相同调用该方法后,程序将生成ok和cancel两个值。

 

Ext.MessageBox.confirm(String title,String msg,Function fn);

Ext.MessageBox.confirm中有值yes和no。一个是/否的对话框代码如下:

 

<body>

 

<h1>消息对话框</h1>

<p>=======================</p>

<p>"Yes/No"对话框</p>

<p><button id="messageBox1">Click Me</button></p>

<script language="javascript">

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(){

Ext.MessageBox.confirm('确认','您确定要执行此操作吗?');

});

});

</script>

</body>

示例3.2实现了一个是/ 否的对话框

提示:如果按钮的文字要显示中文,可以引入下面一个文件:

<script type="text/javascript" src="ext-3.0.0/src/locale/ext-lang-zh_CN.js"></script>

1.1.4 Ext. MessageBox. prompt()

Ext.MessageBox.prompt()方法用于产生输入框,相当于Window.prompt()方法。

 

Ext.MessageBox.prompt(String title,String msg,Function fn,Object Xope,Boolean/Number multiline);

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script type="text/javascript" src="ext-3.0.0/src/locale/ext-lang-zh_CN.js"></script>

</head>

 

<body>

<center>

<h1>消息对话框</h1>

    <p>------------------------</p>

    <p>交互对话框</p>

    <p><button id="messageBox1">click me</button></p>

</center>

</body>

 

<script type="text/javascript">

 

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(){

Ext.MessageBox.prompt('金额','请输入充值金额:'); });

});

 

</script>

</html>

示例 3.3 实现了一个可输入充值卡金额的对话框

修改示例 3.3,处理用户点击 “ok” “cancel” 的不同点击事件

<script language="javascript">

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(){

Ext.MessageBox.prompt('金额','请输入充值金额:',function(bt,text){

if(bt == 'ok'){

Ext.MessageBox.alert('状态','您输入的充值金额:' + text);

}else{

Ext.MessageBox.alert('状态','您取消了充值!');

}    

   });

});

});

</script>

 

1.1.5 Ext. MessageBox. show()

Ext.MessageBox.show()方法功能非常强大,使用 config 配置形式比前面的方法更方便。该方法的参数很多,最常用的配置参数见表 3-1-1。

3-1-1    Ext.MessageBox.show() 参数

参数

说明

animal

对话框弹出和关闭时动画效果,设置为“idName”则从idName处弹出并产生动画,收起动画则相反。

buttons

弹出框按钮的设置,主要包括:Ext.Msg.OK、Ext.Msg.OKCANCEL、Ext.Msg.CANCEL、Ext.Msg.YESNO、Ext.Msg.YESNOCANCEL

closable

默认为true,如果为false,则不显示右上角的关闭按钮

msg

消息的内容

title

标题

fn

关闭弹出框后执行的函数

icon

弹出框内容前面的图标,取值为:Ext.MessageBox.INFO、Ext.MessageBox.ERROR、Ext.MessageBox.WARNING、Ext.MessageBox.QUESTION

width

弹出框的宽度,不带单位

prompt

设为true,则弹出框带有输入框

multiline

设为true,则弹出框带有多行输入框

progress

设为true,显示进度条

progressText

在进度条上显示的文本

wait

设为true,动态显示 progress

waiting

配置参数,以控制 progress 的显示

 

使用 Ext.MessageBox.show()制作带 Yes/No/Cancel 的对话框. 代码如下:

<script type="text/javascript">

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(e){

Ext.MessageBox.show({

title:'保存?',

msg:'您正在关闭一个没有保存的表单,您要保存吗?',

buttons:Ext.MessageBox.YESNOCANCEL,

animEl:'messageBox1'

});

});

});

</script>


在实际应用中,执行十分耗时的操作时,需要使用进度条提示用户耐心等候。在Ext 中,可以使 Ext.MessageBox.show()制作简单的进度条。Ext.MessageBox.show()中提供了一个默认的进度条,此进度条在progress被设置为 true后出现在对话框中,代码如下:

Ext.MessageBox.show({

title:'请稍等...',

msg:'处理中...',

width:300,

progress:true,

closable:false,

animEl:'messageBox1'

});

由图3.1.7 可知,进度条的状态不能轻易向前推进,可以使用 Ext.MessageBox.updateProgress()函数改善进度条状态。一般情况下,进度条可以不直接关闭,而是使用 closable:false 隐藏对话框的关闭按钮。

为了使进度条变化更加形象,使用timeout定时器对进度条进行修改,使进度条的状态随时间变化,为用户显示进度的百分比。

<script language="javascript">

Ext.onReady(function(){

Ext.get('messageBox1').on('click',function(){

Ext.MessageBox.show({

title:'请稍等...',

msg:'处理中...',

width:300,

progress:true,

closable:false,

animEl:'messageBox1'

});

var fv = function(v){

return function(){

if(v == 100){ Ext.MessageBox.hide();}

else{Ext.MessageBox.updateProgress(v/100,'内容加载中,进度'+ v + ' %...');}

}

}

for(var i=1; i<101; i++){

setTimeout(fv(i),i*100);

}

});

});

</script>


1.2 Ext表单控件

表面上,Ext表单控件只是修改了 CSS 样式,但在漂亮的界面下隐藏的仍然是input控件。表单除了前面的功能外还需要数据校验、数据校验失败的提示等,这些功能在传统的表单控件中没有良好的处理方式。在Ext 中,可以通过表单和对应的输入控件,轻易地校验数据,并在校验失败后给予提示,为用户提供良好的交互体验。

1.2.1 Ext表单

使用表单控件,制作简单的Ext表单。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

</head>

 

<body>

<div id="myForm"></div>

<script type="text/javascript">

 

Ext.onReady(function(){

var form = new Ext.form.FormPanel({

defaultType: 'textfield',

labelAlign: 'right',

title: 'form',

labelWidth: 60,

buttonAlign: 'center',

frame: true,

width: 220,

items: [{fieldLabel: 'userName'}],

buttons: [{text: '提交'},{text: '重置'}],

});

form.render("myForm");

});

</script>

</body>

</html>

上述代码创建的 Ext表单中,包含一个单行输入框和两个按钮 (提交、重置)

制作一个 Ext.form.FormPanel,然后设置 field。FormPanel 是 Ext.Panel 的子类,可以对其执行各种 Panel 的操作。使用 FormPanel 的最大优势是易于布局,Ext.form.FormPanel继承了 Ext.Panel。 Panel 可以将 Ext.form.FormPanel 放入 Ext.Viewport 中作为整个页面布局的一部分,同时利用items指定 Ext.form.FormPanel 内部的子组件。

1.2.2 Ext表单控件

Ext提供了许多表单控件,包括 TextField、TextArea、CheckBox、Radio、ComboBox、DateField、HtmlEditor、Hidden 和 TimeField。

1. 基本输入控件 Ext.form.Field

Ext.form.Field是所有表单输入控件的基类,其他输入控件都由它扩展而来。该控件定义了输入控件的通用属性和功能函数,这些属性和功能函数大致分为 3 类:页面显示样式、控件参数配置和数据有效性校验。

1)页面显示样式:clearCls、cls、fieldClass、focusClass、itemCls、invalidClass、labelStyle等属性,分别用于定义不同状态下输入框采用的样式。

2)控件参数配置:autoCreate、disabled、fieldLabel、hideLabel、inputType、labelSeparator、name、readOnly、tablndex、value等属性。

3)数据有效性检验:invalidText、msgFx、msgTarget、validateOnBlue、validateDelay、validateEvent等属性。

以下将通过数据验证说明 Field。在默认的情况下,表单验证的输入控件会监听blur事件,数据验证失败则会根据 msgTarget的设置显示错误消息。通常,msgTarget可以被设置为 qtip、title、side或 under,根据不同的设置,错误信息将以指定的方式显示。所有的输入控件都继承 Ext.form. Field,所以任何表单输入控件都可以改变其错误消息的显示方式。用户登录的验证代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

</head>

<body>

<div id="form"></div>

<script language="javascript">

Ext.onReady(function(){

var field1 = new Ext.form.Field( { fieldLabel: 'userName' , msgTarget:'qtip'} );

var field2 = new Ext.form.Field( { fieldLabel: 'password' , msgTarget:'title'} );

var form = new Ext.form.FormPanel( {

defaultType: 'textfield',

title:'form',

buttonAlign: 'center',

frame:true,

width: 320,

items: [field1,field2],

buttons:[{text: '提交'}]

 } );

 form.render("form");

 field1.markInvalid();

 field2.markInvalid();

});

</script>

</body>

</html>

上述代码使用 marklnvalid()函数显示 field 的错误信息样式。其中,msgTarget分别设置为 qtip 和title。运行程序

2. 文本输入控件 Ext.form.TextField

Ext.form.TextField继承 自 Ext.form.Field,是专用于输人文本的输入控件。除了 Field 的功能外,此控件最主要的特性是检查输入框数据是否为空以及数据的最大、最小长度。添加 TextField功能,代码如下:

var field3 = new Ext.form.TextField({  

fieldLabel: 'tel',

allowBlank: false,

emptyText: 'empty',

maxLength: 16,

minLength: 8,

msgTarget: 'title'

});


3. 多文本输入控件 Ext.form.TextArea

Ext.form.TextArea与Ext.formiTextField都是用于输人文本的输入控件,但是,TextArea可以输入多行文本。

 var field4 = new Ext.form.TextArea({

 width: 122,

 grow: true,

 preventScrollbars:true,

 fieldLabel: '备注',

 emptyText: '请输入备注信息',

 maxLength: 100,

 minLength: 10

});

var form = new Ext.form.FormPanel( {

defaultType: 'textfield',

title:'form',

buttonAlign: 'center',

frame:true,

width: 320,

items: [field1,field2,field3,field4],

buttons:[{text: '提交'}]

 } );


4. 日期输入控件 Ext.form.DateField

Ext.form.DateField 是常用的日期选择控件。除了选择日期功能外,此控件还支持 Ext.form.TextField和 Ext.form.Field 中定义的功能。

var field5 = new Ext.form.DateField({

 fieldLabel: '出生日期',

 allowBlank: false,

 emptyText: '请输入出生日期',

 format: 'Y-m-d',

 disabledDays:[0,6]

});

 


5. 时间输入控件 Ext.form.TimeField

使用日期控件后,有时应用程序还需要精确到日期的具体时间。Ext.form.TimeField是用于选择时间的输入控件,它可以通过指定一天的开始时间、结束时间以及时间间隔选择时间。

var field6 = new Ext.form.TimeField({

fieldLabel: '时间',

emptyText: '请选择',

minValue: '1:00 AM',

maxValue: '23:00 PM',

increment:60

});


6. 在线编辑器控件 Ext.form.HtmlEditor

HTML 中包含许多在线编辑器,但其使用较复杂。Ext提供了简单的在线编辑器控件 Ext.form.HtmlEditor,可以对文本进行各项设置。

var field7 = new Ext.form.HtmlEditor( {

fieldLabel: '自我介绍',

anableAlignments:true,

enableColors:true,

enableFont: true,

enableFontSize: true,

enableLinks: true,

enableFormat: true,

enableLists: true,

enableSourceEdit: true,

autoHeight: 'auto',

anchor: '90%'

});   

由以上代码可知,可以通过相应的enable选项启用或禁用来设置各种功能

7. 隐藏域控件 Ext.form.Hidden

在实际应用中,修改记录信息时,信息 ID 一般不显示给用户,但该 ID 需要在页面使用时,一般必须隐藏 ID 值。在Ext 中,可以使用隐藏域控件 Ext.form.Hidden 来隐藏不需要呈现给用户的信息,该控件直接继承自 Ext.form.Field,通过Hidden的 setValue()和 getValue()函数赋值和取值,且值不显示在页面上。

var field8 = new Ext.form.Hidden({

fieldLabel: 'empId'

});

field8.setValue('0003');

var empId = field8.getValue();   

运行上述代码,页面中将产生隐藏域 empId=0003。

1.2.3 表单提交

表单最重要的功能就是向后台提交数据,下面通过一个注册功能演示Ext表单提交,Ext代码如下所示。

Ext.onReady(function() {

var form = new Ext.form.FormPanel( {

title : '用户登陆',

bodyStyle : 'padding:15px',

frame : true,

layout : 'form',

width : 350,

defaultType : 'textfield',

defaults : {

width : 230

},

labelAlign : 'right',

buttonAlign : 'center',

labelWidth : 65,

labelPad : 13,

url:'login_action.jsp',

items : [ {

fieldLabel : '账号',

name : 'name',

allowBlank : false

}, {

fieldLabel : '密码',

inputType : 'password',

name : 'password'

} ],

buttons : [ {

text : '提交',

listeners:{

click:function(){

form.getForm().submit({

success:function(f,a){

Ext.Msg.alert("提示",a.result.msg);

},

failure:function(f,a){

Ext.Msg.alert("提示",a.result.msg);

}

});

}

}

}, {

text : '取消'

} ]

});

form.render("form");

});

 

上面代码中,为了提交数据,要为form设置一个url参数,表示表单数据提交到该路径。记得要给TextField加上一个name属性,这样后台程序才可以通过这个属性值获取提交的值。最后看Ext的按钮,在【提交】按钮上,使用listeners配置项处理事件,值是一个JSON对象,该JSON对象的属性是事件名称,值是事件处理函数。在本例中当点击按钮后,获取FormPanel包含的BasicForm对象,然后再调用submit()函数即可完成提交。

在本例中的提交到的后台程序login_action.jsp代码如下所示。

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%

String name = request.getParameter("name");

String password = request.getParameter("password");

if("admin".equals(name)&&"admin".equals(password)){

out.print("{success:true,msg:'登陆成功,正在转向主页面'}");

} else {

out.print("{success:false,msg:'登陆失败,请检查账号和密码'}");

}

%>

上面代码用来处理登陆请求,首先得到提交的账号和密码,如果都是admin时登陆成功,此时响应一个JSON对象“{success:true,msg:'登陆成功,正在转向主页面'}”,其它情况登陆失败,此时响应一个JSON对象“{success:false,msg:'登陆失败,请检查账号和密码'}”,Ext控件就会根据这个对象的success属性的值来确定是成功或者失败。

如果账号和密码都输入admin运行结果如图3.1.17所示

1.3 Ext树控件

在应用程序中,经常需要显示或处理树状结构的对象信息,如部门信息、地区信息、菜单信息操作系统中的文件夹信息等。

传统的 HTML页面显示树比较因难,需要编写大量的 JavaScript代码。而且基于Ajax异步加载的树不但涉及Ajax数据加载及处理技术,还需要考虑跨浏览器支持等,处理过程繁琐。ExtJS中提供了树控件,可以在B/S应用中快速开发包含树结构信息的应用。

1.3.1 基本树结构

树控件由 Ext.tree.TreePanel类定义,TreePanel类继承自 Panel面板。简单的树代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(function (){

var root = new Ext.tree.TreeNode( {id:'root', text: '根节点'} ) ;

var child = new Ext.tree.TreeNode( {id:'child', text: '子节点'} ) ;

root.appendChild(child);

var tree = new Ext.tree.TreePanel({

renderTo: 'myTree',

root: root,

width:200

});

});

</script>

</head>

<body>

<div id="myTree" style="height:300px"></div>

</body>

</html>     

上述代码中,使用 new Ext.tree.TreeNode类创建树的根节点和子节点,然后使用树节点 root 的appendChild方法向该节点中添加一个子节点,最后直接使用 new Ext.tree.TreePanel创建树面板,在树面板的初始化参数中指定树的 root属性值为前面创建的 root节点,即树根节点。

1.3.2 Ext树控件TreeNodeTreeLoader

Ext JS中,叶子节点、非叶子节点统一使用 TreeNode 表示树的节点。树节点包括两种类型:①普通的简单树节点,由Ext.tree.TreeNode定义;需要异步加载子节点信息的树节点,由Ext.tree.AsyncTreeNode定义。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(function (){

var root = new Ext.tree.TreeNode( {id:'root', text: '根节点'} ) ;

var child1 = new Ext.tree.TreeNode( {id:'child1', text: '子节点1'} ) ;

var child2 = new Ext.tree.AsyncTreeNode( {id:'child1', text: '子节点1'} ) ;

root.appendChild(child1);

root.appendChild(child2);

root.expanded=true;

var tree = new Ext.tree.TreePanel({

renderTo: 'myTree',

root: root,

width:200

});

});

</script>

</head>

<body>

<div id="myTree" style="height:300px"></div>

</body>

</html>     

上述代码同时使用了 TreeNode 和 AsyncTreeNode

上述代码没有指定树的加载器,树一直尝试加截子节点 2。普通的 TreeNode可以通过调用节点的 appendChild、removeChild 等方法向该节点中添加子节点或删除子节点等。而树加载器TreeLoader 是一个关键的部件,由 Ext.tree.TreeLoader 类定义,只有 AsyncTreeNode 才会使用 TreeLoader。

使用 TreeLoader需要首先使用 Ext.tree.TreeLoader 初始化一个 TreeLoader 对象,构造函数中的配置参数 url 表示获得树节点信息的 url。然后,使用 AsyncTreeNode 初始化根节点,在该节点中指定节点的 loader 为前面定义的 loader。执行程序后点击“根节点”时,会从服务器踹指定 root 节点的子节点信息。

严格地说,TreeLoader 是针对树的节点定义的,可以为树中每个节点定义不同的 TreeLoader。默认情况下,如果一个 AsyncTreeNode 节点准备加载子节点,但节点上没有定义 loader 时,会使用 TreePanel 中定义的 loader作为加载器。因此,可以直接在TreePanel上指定 loader属性,避免为每个节点指定具体的 TreeLoader。

实际上,读取本地JSON是一种使用 TreeLoader 的另类方法。某些情况下,树的数据并不多,为了减少数据量而使用Ajax访问后台并不合适;每个节点都使用 New生成又过于麻烦。此时,可以使用 TreeLoader 读取本地JavaScript数据生成需要的树节点。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>无标题文档</title>

<link rel="stylesheet" type="text/css" href="ext-3.0.0/resources/css/ext-all.css"/>

<script type="text/javascript" src="ext-3.0.0/adapter/ext/ext-base.js"></script>

<script type="text/javascript" src="ext-3.0.0/ext-all.js"></script>

<script language="javascript">

Ext.onReady(function (){

var tree = new Ext.tree.TreePanel({

renderTo: 'myTree', //应用到的HTML元素ID

animate:true,//以动画形式伸展,收缩子节点

title: 'EXT静态树',

collapsible:true,

rootVisible:true,//是否显示根节点

autoScroll:true,

autoHeight:true,

width: 250,

lines:true,//节点之间连接的横竖线

loader: new Ext.tree.TreeLoader(),

root: new Ext.tree.AsyncTreeNode({

id: 'root',

text:'根节点',//节点名称

expanded:true,//展开

leaf:false,//是否为叶子节点

children:[

{id: 'child1',text: '子节点一', leaf:true},

{id: 'child2',text: '子节点二',children: [ {text:'子节点二的子节点' } ]} ]

})

});

});

</script>

</head>

<body>

<div id="myTree" style="height:300px"></div>

</body>

</html>    


上述示例中,TreePanel包括许多参数设置,见表 10-1-2。

 

3-1-2    TreePanel 的配且参数

名称

说明

animate

true表示展开、收缩动画,false表示没有动画效果

autoHeight

true表示自动高度,默认为false

enableDrag

true表示树的节点可以拖动Drag

enableDD

可以拖动以及通过Drag改变节点的层次结构

Lines

节点间的虚线

Loader

加载节点数据

root

根节点

rootVisible

false表示不显示根节点,默认为true

trackMouseOver

false表示mouseover无效果

useArrows

小箭头


  

本章总结

Ø Ext中的 MessageBox是一种特殊的窗口,配置简单,可以任意拖动、摆放,也可以实现对任何控件的使用。

Ø Ext.MessageBox为程序员提供了弹出提示框的简单方法,使用它提供的 alert、confirm、prompt等对话框完全可以替代传统的同类对话框。此外,Ext.MessageBox还提供了进度条等功能。

Ø Ext.MessageBox.show()方法功能非常强大,使用 config 配置形式比前面的方法更方便。

Ø Ext.form.FormPanel作为表单容器,然后设置 field。使用 FormPanel 的最大优势是易于布局,利用items指定 Ext.form.FormPanel 内部的子组件。

Ø Ext提供了许多表单控件,包括 TextField、TextArea、CheckBox、Radio、ComboBox、DateField、HtmlEditor、Hidden 和 TimeField。

Ø 树控件由 Ext.tree.TreePanel类定义,树中的每个节点都是一个TreeNode对象。 

任务实训部分

1:应用Ext消息对话框

训练技能点

Ø Ext消息对话框

需求说明

当点击按钮后,使用Ext. MessageBox. show()方法实现一个自定义图标、按钮的对话框,效果如图3.2.1所示。

 

3.2.1 自定义对话框

实现步骤

(1) 处理点击按钮事件

(2) 使用Ext. MessageBox. show()实现自定义对话框

参考代码

<!DOCTYPE HTML>

<html>

  <head>

  <title>ExtJS</title>

  <meta http-equiv="content-type" content="text/html; charset=UTF-8">

  <link rel="stylesheet" href="extjs/resources/css/ext-all.css" type="text/css"></link>

  <script type="text/javascript" src="extjs/adapter/ext/ext-base-debug.js"></script>

  <script type="text/javascript" src="extjs/ext-all-debug.js"></script>

  <script type="text/javascript">

Ext.onReady(function() {

Ext.get("btn").on("click", function() {

Ext.Msg.show( {

title : '提示',

msg : '输入你的住址',

width : 300,

buttons : Ext.MessageBox.OKCANCEL,

multiline : true,

fn : function(btn, text) {

Ext.Msg.alert("结果", text);

},

animEl : 'btn',

icon : Ext.MessageBox.QUESTION

});

});

});

  </script>

  </head>

  <body>

    <input type="button" id="btn" value="ClickMe">

  </body>

</html>

 

2:使用Ext实现注册界面

训练技能点

Ø Ext表单控件

需求说明

使用Ext表单控件实现注册页面,效果如图3.2.2所示。

 

3.2.2 注册界面

实现步骤

(1) 使用FormPanel作为界面容器

(2) FormPanel容器中添加其它控件

参考代码

Ext.onReady(function() {

Ext.QuickTips.init();

var form = new Ext.form.FormPanel( {

labelAlign : 'right',

labelWidth : 50,

buttonAlign : 'center',

width : 450,

autoHeight : true,

title : 'form',

frame : true,

defaults : {

width : 300

},

defaultType : 'textfield',

items : [ {

fieldLabel : '账号',

name : 'name'

}, {

fieldLabel : '密码',

inputType : 'password',

name : 'password'

}, {

xtype : 'numberfield',

fieldLabel : '年龄',

name : 'age'

}, {

xtype : "combo",

fieldLabel : '性别',

hiddenName:'sex',

store : new Ext.data.SimpleStore( {

fields : [ 'value', 'text' ],

data : [ [ 'M', '' ], [ 'F', '' ] ]

}),

displayField : 'text',

valueField : 'value',

mode : 'local',

emptyText : '请选择'

}, {

xtype : 'datefield',

fieldLabel : '生日',

format:'Y-m-d',

name : 'birthday'

}, {

xtype : 'textarea',

fieldLabel : '简介',

name : 'controduce'

} ],

buttons : [ {

text : '注册',

listeners:{

click:function(){

form.getForm().submit({

});

}

}

}, {

text : '取消'

} ]

});

form.render("form");

});

3:使用Ext实现注册功能

训练技能点

Ø Ext表单控件

需求说明

在任务2的基础上完成注册功能,当用户点击【注册】按钮后,提交到后台程序并保存到数据库,保存成功或失败给出提示,效果如图3.2.3所示。

 

3.2.3 注册功能

实现步骤

(1) 使用FormPanel的url属性指定提交路径。

(2) 处理【注册】按钮点击事件,当点击后提交请求到后台处理程序完成注册。

参考代码

核心代码如下所示。

buttons : [ {

text : '注册',

listeners:{

click:function(){

form.getForm().submit({

success:function(f,a){

Ext.Msg.alert("提示",a.result.msg);

},

failure:function(f,a){

Ext.Msg.alert("提示",a.result.msg);

}

});

}

}

}, {

text : '取消'

} ]

 

4:使用Ext实现树结构

训练技能点

Ø Ext树控件

需求说明

实现一个管理系统的树结构,效果如图3.2.4所示。

 

3.2.4 管理系统树结构

实现步骤

(1) 使用TreePanel作为容器。

(2) 向容器中添加树节点。

参考代码

核心代码如下所示。

Ext.onReady(function() {

var tree = new Ext.tree.TreePanel( {

collapsible : true,

title : '管理菜单',

width : 200,

autoScroll : true,

split : true,

loader : new Ext.tree.TreeLoader(),

root : new Ext.tree.AsyncTreeNode( {

text : '系统管理',

expanded : true,

icon : 'img/13.png',

children : [ {

text : '用户管理',

icon : 'img/users.png',

children : [ {

text : '用户角色',

icon : 'img/user.png',

leaf : true

}, {

text : '用户权限',

icon : 'img/usericon.png',

leaf : true

} ]

}, {

text : '客户管理',

icon : 'img/60.png',

children : [ {

text : '客户维护',

icon : 'img/61.png',

leaf : true

}, {

text : '客户关系',

icon : 'img/62.png',

leaf : true

} ]

},{

text : '系统设置',

icon : 'img/90.png',

children : [ {

text : '字典设置',

icon : 'img/91.png',

leaf : true

}, {

text : '数据清除',

icon : 'img/92.png',

leaf : true

} ]

}]

})

 

});

tree.render("tree");

tree.expandAll();

});

 

 

巩固练习部分

一、选择题

   1、 进度条一般不直接关闭,通常情况下可以使用 )隐藏对话框的关闭按钮。

    A. closable:false

    B. closable:true

    C. progress:false

    D. progress:true

2. “Ext.MessageBox.confirm("title","msg",function(e){alert(e);});”中 function 的参数e是 (   )

    A. 点击的弹出框的按钮的值

    B. 点击的弹出框的标题的值

    C. 点击的弹出框的内容的值

    D. 点击的弹出框的关闭按钮的值

3. 使用 Ext 的 (   ),可以替代传统的 alert、confirm等方法产生的对话框。

    A. Ext. MessageBox

    B. Ext. form

    C. Ext. tree

    D. Ext. Gird

4. Ext 中提供制作进度条的是 (   )

    A. Ext.MessageBox. alert()

    B. Ext.MessageBox. con finn()

    C. Ext.MessageBox. prompt()

    D. Ext.MessageBox.show()

5. 在默认情况下,表单验证的输入控件会监听blur事件,如果数据验证失败,则根据msgTarget的设置显示错误消息。通常,msgTarget可以被设置为 (   )

    A. qtip

    B. title

    C. side

    D. under

二、简答题

Ext.form.Field定义的输入控件包含哪些通用的属性和功能函数?

三、操作题

使用 Ext JS表单控件制作论坛中用户的注册页面,在用户提交注册信息时使用进度条。

作者:zhangchen124 发表于2017/3/21 20:30:22 原文链接
阅读:166 评论:0 查看评论

linux驱动开发module(2) 原理

$
0
0

前言

前文中介绍了 module 的基本组成部分,现在在上一节的基础上,对 module 做一点点深入的理解。

正文

我们的 module 模块,如果动态的加载到内核中,通常在 Makefile 中,以这样的形式进行标识

obj-m +=first_drv.o 

如果静态的加载到内核中,使用的是下列的方式

obj-y +=first_drv.o 

module_init分析

module_init 这个宏在 include/linux/init.h 这个目录下,一下仅仅摘录和module相关的代码

typedef void (*exitcall_t)(void);
#ifndef MODULE

#define __define_initcall(level,fn,id) \
    static initcall_t __initcall_##fn##id __used \
    __attribute__((__section__(".initcall" level ".init"))) = fn

#define device_initcall(fn)     __define_initcall("6",fn,6)

#define __initcall(fn) device_initcall(fn)

#define __exitcall(fn) \
    static exitcall_t __exitcall_##fn __exit_call = fn

#define module_init(x)  __initcall(x);
#define module_exit(x)  __exitcall(x);

#else 
#define module_init(initfn)                 \
    static inline initcall_t __inittest(void)       \
    { return initfn; }                  \
    int init_module(void) __attribute__((alias(#initfn)));
#define module_exit(exitfn)                 \
    static inline exitcall_t __exittest(void)       \
    { return exitfn; }                  \
    void cleanup_module(void) __attribute__((alias(#exitfn)));
  • 首先解决第一个疑惑,这里列举了两个 module_init ,到底选择哪一个 module_init

  • 这两个 moudle_init 使用一个 MODULE 的宏进行分隔,这里的 MOUDLE 是在 Makefile 中进行确定是否进行定义的,前边知道如果编译为模块在 makefile 中会使用 obj-m,此时使用的是第二个 module_init 的定义。

动态加载

动态加载使用的命令为 insmod 或者 rmmod ,在加载模块的时候,只会加载默认的init_module cleanup_module 这两个函数;所以使用 module_initmodule_exit 这两个宏的目的就是给我们写的入口函数和出口函数定义一个别名为 module_initmodule_exit,这样就能实现正常的加载。

在这里使用了 _attribute_((alias(#initfn))); 进行定义别名。

## 静态加载

静态加载的时候,会将入口函数,和出口函数,分别放入对应的 section 段中。
具体可参考如下文章
module_init宏分析

总结

静态加载的模块,存放在特定的 section 段中,静态加载模块,使用module_init这个宏给起一个别名 init_module,供加载模块的是进行调用。

参考文献

#ifdef MODULE 关于MODULE的问题
module_init宏分析

作者:u013377887 发表于2017/3/21 20:32:36 原文链接
阅读:67 评论:0 查看评论

POJ - 1611 并查集

$
0
0

           思路:求与0连通的学生数,包含0自身。

AC代码:

#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000") 
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int> 
typedef long long LL;
const int maxn = 30000 + 5;
int p[maxn];
int find(int x) {
	return p[x] == x ? x : p[x] = find(p[x]);
}
void join(int x, int y) {
	int px = find(x), py = find(y);
	if(px != py) p[px] = py;
}
int main() {
	int n, m;
	while(scanf("%d%d", &n, &m) == 2 && n+m) {
		for(int i = 0; i < n; ++i) p[i] = i;
		int num, x, y;
		for(int i = 0; i < m; ++i) {
			scanf("%d%d", &num, &x);
			for(int j = 1; j < num; ++j) {
				scanf("%d", &y);
				join(x, y);
				x = y;
			}
		}
		int goal = find(0);
		int ans = 0;
		for(int i = 0; i < n; ++i) {
			if(find(i) == goal) ++ans;
		}
		printf("%d\n", ans);
	}
	return 0;
}

如有不当之处欢迎指出!
作者:flyawayl 发表于2017/3/21 20:59:10 原文链接
阅读:71 评论:0 查看评论

STL一级空间配置器

$
0
0

在STL中,空间配置器是容器必不可少的东西,它为容器中的数据提供空间存储,由于考虑小型区块可能造成的内存碎片问题,STL中设计了双层级配置器,当开辟内存>128bytes时,就会调用第一级配置器,在这里我们将根据其源码模拟实现它的第一级配置器。

STL 第一级配置器


代码实现:

#pragma once

//一级空间配置器
#define __THROW_BAD_ALLOC 0
template <int inst>
class __MallocAllocTemplate 
{
public:
	static void * Allocate(size_t n)
	{
		void* result=malloc(n);
		if(result==0)
		{
			//若开辟失败调用__Oom_Malloc函数
			result=__Oom_Malloc(n);
		}
		return result;
	}
	static void Deallocate(void *p)
	{
		free(p);//直接调用free
	}


	static void * Reallocate(void *p, size_t new_sz)
	{
		void* result=realloc(p,new_sz);
		if(result==0)
		{
			result=__Oom_Realloc(p,new_sz);
		}
		return result;
	}


	//用户自己定义内存不足情况下的处理函数
	static void (* Set_Malloc_Handler(void (*f)()))() 
	{
		void (* old)() = __Malloc_Alloc_Oom_Handler;
		__Malloc_Alloc_Oom_Handler = f;
		return(old);
	}
private:
	static void (* __Malloc_Alloc_Oom_Handler)();
	
	//处理内存不足情况

	static void *__Oom_Malloc(size_t n)
	{
		void (*My_Malloc_Handler)();
		void* result;
		while(1)//***用户需小心使用自己定义的处理函数,否则会使程序陷入死循环
		{
			My_Malloc_Handler=__Malloc_Alloc_Oom_Handler;//用户自己的处理函数地址
			if(My_Malloc_Handler==0)
			{
				throw __THROW_BAD_ALLOC;
			}
			(*My_Malloc_Handler)();//调用处理函数,释放内存
			result=malloc(n);//再次开辟内存
			if(result)
				return result;
		}
	}
	static void *__Oom_Realloc(void *p, size_t n)
    {
		void(*My_Malloc_Handler)();
		void* result;
		while(1)
		{
			My_Malloc_Handler=__Malloc_Alloc_Oom_Handler;
			if(My_Malloc_Handler==0)
			{
				throw __THROW_BAD_ALLOC;
			}
			(*My_Malloc_Handler)();
			result=realloc(p,n);
			if(result)
				return result;
		}
	}
};

template <int inst>
void (* __MallocAllocTemplate<inst>::__Malloc_Alloc_Oom_Handler)() = 0;//默认为0
typedef __MallocAllocTemplate<0> malloc_alloc;

void Test()
{
	int* pa=(int*)malloc_alloc::Allocate(sizeof(int)*5);
	for(size_t i=0;i<5;++i)
	{
		pa[i]=i;
	}

	pa=(int*)malloc_alloc::Reallocate(pa,sizeof(int)*8);
	for(size_t i=5;i<8;++i)
	{
		pa[i]=i*10;
	}
	malloc_alloc::Deallocate(pa);
}
以上实现中简单测试了结果。

由上代码可知:第一级配置器以malloc()、free()、realloc()等C函数执行实际的内存配置、释放等操作,并实现模拟了C++new-handler机制,即当系统无法开辟内存时调用一个用户指定的处理机制,当用户设定时,它则会不断调用处理机制函数,直到获得内存成功返回,所以客户在指定时要小心使用,以防程序陷入死循环崩溃;但如果用户没有设定,由上程序可知__Malloc_Alloc_Oom_Handler() = 0默认为0,即处理内存不足的函数直接抛出异常。

作者:L_XRUI 发表于2017/3/21 21:13:12 原文链接
阅读:134 评论:0 查看评论

《华为机试在线训练》之去空格后整数求和

$
0
0

一,题目要求

1,题目描述:编写一个程序,要求用户输入一串整数和任意数目的空格,这些整数必须位于同一行中,但允许出现在该行中的任何位置。当用户按下键盘上的“Enter”按键时,数据输入结束。程序自动对所有的整数进行求和并打印结果

2,输入例子:22    2 2             4

3,输出例子:30

二,思路分析

1,C语言实现

(1)方法1

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i;
    char ch;
    int sum=0;
    printf("请输入一串整数和任意数目的空格:\n");
    //一直到输入的值是整数的时候进入while循环,当输入字符时,scanf返回0,什么都不读,然后再次调用scanf
    while (scanf("%d",&i)==1)    //scanf正常结果是为1的
    {
        sum += i;
        while ((ch = getchar()) == ' ')//屏蔽空格
            ;
        if (ch == '\n')
        {
            break;
        }
        ungetc(ch,stdin);//将变量ch中存放的字符退回给stdin输入流,获取多的退回
    }
    printf("结果是:%d\n",sum);
    system("pause");
    return 0;
}

      结果如图1所示

                                        

                                                                                                              图1 方法一结果图

(2)方法2

#include <stdio.h>

int main() {

    int num = 0,sum = 0;

    char ch;

    while((ch = getchar()) != '\n')
    {

        if(ch >= '0' && ch <= '9')
            num = 10 * num + ch - '0';

        if(ch == ' ')
            {

               sum += num;

               num = 0;

            }
    }
    sum = sum +num;
    printf("sum = %d\n",sum );

    return 0;

}

      结果如图2所示

                                   

                                                                                                              图2 方法二结果图
2,C++语言实现

      

#include <iostream>

using namespace std;

int main()
{
    int sum = 0;

    cout << "请输入一串整数和任意数目的空格:" << endl;

    int i;
    while( cin >> i)
    {
        sum += i;
        while( cin.peek() == ' ')
        {
            cin.get();
        }
        if(cin.peek() == '\n')
        {
            break;
        }
    }

    cout << "结果是:" << sum << endl;
    return 0;
}

     结果为图3所示

                           

                                                                                      图3  C++实现结果图

           

作者:huangchijun11 发表于2017/3/21 21:15:58 原文链接
阅读:68 评论:0 查看评论

EffectiveJava(33) -- EnumMap详解(使用EnumMap代替序数)

$
0
0

因为数组不能与泛型兼容 , 所以当你要使用 ordinal 方法来索引数组的代码的时候,应该考虑使用 EnumMap .
EnumMap 在内部使用了数组,它也是Map的一个实现类 , Map 的实现类有很多种,EnumMap 从名字我们可以看出这个Map是给枚举类用的。它的key为枚举元素 ,value自定义。在工作中我们也可以用其他的Map来实现我们关于枚举的需求 ,但是为什么要用这个EnumMap呢?因为它的性能高 !为什么性能高?因为它的内部是用数组的数据结构来维护的!
例如 – 当你要按照类型将元素列出来 我们是用 enum 的 ordinal 和 EnumMap 分别实现进行比较

public class Herb {
    public enum Type {
        ANNUAL, PERENNTAL, BIENNIAL
    }

    // private static final Herb Type = null;
    private final String name;
    private final Type type;

    Herb(String name, Type type) {
        this.name = name;
        this.type = type;
    }

    @Override
    public String toString() {
        return name;
    }

    // 将集合放到一个按照类型的序数进行索引的数组中来实现  替换
    Herb[] garden = { new Herb("1", Type.ANNUAL), new Herb("2", Type.BIENNIAL), new Herb("3", Type.PERENNTAL) };

    Set<Herb>[] herbsByType = (Set<Herb>[])new Set[Herb.Type.values().length];
    for(int i = 0;i<herbsByType.length;i++){
        herbsByType[i] = new HashSet<Herb>();
    }
    for(Herb h:garden){
        herbsByType[h.type.ordinal()].add(h);
    }   
}}

上面提到过 , 数组不能与泛型兼容 , 程序需要进行未受检转换 .因为数组不知道他的索引代表什么 , 你必须手工标注这些索引的输出 . 当你这么做时 , 访问一个按照枚举的序数进行索引的数组时 , 使用正确的 int 值就是你的指责了; 而在这个程序中使用 int 值是不安全的.
所以 , 我们可以使用 EnumMap 来快速实现这个功能

Herb[] garden = { new Herb("1", Type.ANNUAL), new Herb("2", Type.BIENNIAL), new Herb("3", Type.PERENNTAL) };
    Map<Herb.Type, Set<Herb>> herbsByType = new EnumMap<Herb.Type,Set<Herb>>(Herb.Type.class);
    for(Herb.Type t:Herb.Type.values()){
        herbsByType.put(t, new HashSet<Herb>());
    }
    for(Herb h:garden)
        herbsByType.get(h.type).add(h); 
    System.out.println(herbsByType);

从上面的例子我们可以看到 , EnumMap内部使用了数组和 Map , 它集 Map 的丰富功能和类型安全的与数组的快速于一身 .

除此之外我们还可以用 EnumMap 对按照序数进行索引的数组的数组进行操作
这个例子模拟了自然界固态液态气态之间的转换 .

public enum Phase {
    SOILD,LIQUID,GAS;
    public enum Transition{
        MELT(SOLID,LIQUID),FREEZE(LIQUID,SOLID),BOIL(LIQUID,GAS),CONDENSE(GAS,LIQUID),SUBLIME(SOLID,GAS),DEPOSIT(GAS,SOLID);

        private final Phase src;
        private final Phase dst;

        private Transition(Phase src,Phase dst) {
            this.src = src;
            this.dst = dst;
        }
        //由键为源Phase,值为map组成的Map,其中组成键的Map是由键值对目标Phase/Transition组成
        private static final Map<Phase, Map<Phase,Transition>> m = new EnumMap<Phase, Map<Phase,Transition>>(Phase.class);
        static{
            //初始化外部map,得到三个空的map
            for(Phase p:Phase.values()){
                m.put(p, new EnumMap<Phase,Transition>(Phase.class));
            }
            //利用每个状态过渡常量提供的起始信息和目标信息初始化内部的map
            for(Transition trans :Transition.values()){
                m.get(trans.src).put(trans.dst, trans);
            }

        }
        public static Transition from(Phase src,Phase dst){
            return m.get(src).get(dst);
        }
    }
}

如果要添加一个 plasma 阶段 , 为了更新基于数组的程序 , 必须给 Phase 添加一种新常量 , 给 Phase.Transition 添加两种新常量 . 如果给数组添加元素过多或者过少或者放置元素不妥当 , 都会运行时失败 . 为此 , 我们必须将 plasma 添加到 Phase 列表 , 并将 IONIZE(GAS,PLASMA) 和 DEIONIZE(PLASMA,GAS) 添加到 Phase.Transition 的列表中 . 其他事情程序会自行处理 , 你几乎连出错机会都没有

总结: 最好不要用序数来索引数组 . 如果你所表示的这种关系是多维的 , 就使用 EnumMap<…,EnumMap<…>> . 应用程序的程序员在一般情况下都不使用 Enum.ordinal , 即使要用也是因为特殊情况 .

作者:JacXuan 发表于2017/3/21 22:19:27 原文链接
阅读:713 评论:0 查看评论

第五届蓝桥杯【省赛试题10】小朋友排队

$
0
0

题目描述:

n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。
每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
【数据格式】
输入的第一行包含一个整数n,表示小朋友的个数。
第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。
例如,输入:
3
3 2 1
程序应该输出:
9
【样例说明】
首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。
【数据规模与约定】
对于10%的数据, 1<=n<=10;
对于30%的数据, 1<=n<=1000;
对于50%的数据, 1<=n<=10000;
对于100%的数据,1<=n<=100000,0<=Hi<=1000000。
资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。

题目思路:

题目要球小朋友的不高兴程度的最小和。那么我们就让每一个小朋友的不高兴程度最低。那么每个小朋友的不高兴程度最分别是多少呢。试想假设一共有n个小朋友,小明是其中的一个小朋友,那么如果左边有比他高的,因为每次只能交换相邻的两个小朋友,因此小明最少需要交换的次数就是他左边比他身高高的小朋友的个数。同理,如果他的右边的小朋友比他的身高低的有x个,那么他还需要至少交换x次。当小明的左右两边分别都是比他高和比他低的小朋友,那么小明则不需要再移动。假设小明左边比他高的有x个,右边比他低的有y个,那么小明的最少移动次数就是x+y。因此每个小朋友的最小移动次数=左边比他高的个数+右边比他低的个数。求出最小移动次数不难用两次for循环来实现。但是复杂度为O(N*N),而题目的测试数据较大,所以不能用这样的方法求解。这里用到了树状数组来求解逆序对数的算法,时间复杂度是NO(logN)。题目思路很容易想到,主要是求逆序对的方法。如果不知道高效的算法,利用两层for循环暴力求解也是可以得一部分分数的。好像归并排序也可以优化,如果有熟悉归并排序的可以尝试一下。

题目代码:

#include<cstdio>
#include<cstring>
#include<iostream> 
#define maxn 100005 
#define MAXN 1000005
using namespace std;

int c[MAXN],  a[MAXN];
long long b[maxn];
int n;

//获取最小比特 
int lowbit(int x)
{
	return x & (-x);	
}

//获取前x项和
int getSum(int x)
{
	int s = 0;
	for(int i = x; i; i -= lowbit(i))
		s += c[i];
	return s;
} 

//修改更新 
void add(int x, int val)
{
	for(int i = x; i < MAXN; i += lowbit(i)){
		c[i] += val;
	}
}


int main()
{
	scanf("%d",&n);
	//左边逆序对 
	memset(c,0,sizeof(c));
	for(int i = 0; i < n; i++){
		scanf("%d", &a[i]);
		add(a[i] + 1, 1);
		b[i] = (i + 1) - getSum(a[i] + 1);
	
	}
	//右边逆序对 
	memset(c, 0, sizeof(c));
	for(int i = n-1; i >= 0; i--){
		add(a[i] + 1, 1);
		b[i] += getSum(a[i]);
	}
	long long ans = 0;
	for(int i=0; i<n; i++){
		ans += (1 + b[i]) * b[i] / 2;
	}
	
	printf("%lld\n",ans);
	
}



作者:qq_34594236 发表于2017/3/21 22:52:32 原文链接
阅读:155 评论:0 查看评论

ZSTU-4272-最佳淘汰算法【优先队列】

$
0
0

Description

Lyf在做操作系统作业的时候,遇到了一题要他实现下Opt算法(全称页面置换最佳淘汰算法)。可是Lyf发现最近好忙啊,于是他想请他的学弟,学妹们帮他来完成。
作业里的内容是这样的:
提出最佳页面淘汰算法。是操作系统存储管理中的一种全局页面替换策略当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。它所产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言。但是我们在这里会告诉你一个已经存在的一个页面序列,请输出最终在内存中存在的页面即可。

Input
有多组数据(组数<=21)。
每组数据输入形如:
n m
a1 a2 a3 a4 …. an
其中n(n,m<=500000)表示已知页面序列的长度。
ai(0<=ai<=100000)表示页面类型,为整数。
m为在内存中保存的页面类型数量。

Output
输出形如:
b1 b2 b3 …. bk
具体要求请仔细阅读样例和Hint。

Sample Input
21 3
7 0 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
3 2
2 1 3
4 3
1 0 0 1

Sample Output
7 0 1
3 1
1 0

题目链接:ZSTU-4272

题目思路:
1.预处理每个数,下一个相同的数最近的位置
2.处理出第一次填满b数组的答案
3.处理替换情况

以下是代码:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <functional>
#include <numeric>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <deque>
#include <list>

using namespace std;
#define maxn 500005
const int INF = 600000;
int a[maxn];
int b[maxn];//记录答案
int vis[maxn];
int mp[maxn + 50];
int nxt[maxn + 50];
struct node{
    int pos,dis,v;
    friend bool operator < ( node a, node b ){
        if(a.dis!=b.dis) return a.dis<b.dis;
        else return a.v<b.v;
    }
};
void init()
{
    for (int i = 0; i < maxn - 1; i++) b[i] = -1;
    memset(vis, 0, sizeof vis);
    memset(mp, 0, sizeof mp);
    memset(nxt, 0, sizeof nxt);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        init();
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
        }
        //预处理下一个a[i]所在位置
        for (int i = n; i >= 1; i--)
        {
            if (mp[a[i]] == 0)
            {
                mp[a[i]] = i;
                nxt[i] = i;
            }
            else
            {
                nxt[i] = mp[a[i]];
                mp[a[i]] = i;
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            if (nxt[i] == i)
            {
                nxt[i] = INF;
            }
        }
        int pos = 1;
        int j = 0;
        priority_queue<node> q;
        //处理出第一次填满b数组的答案
        for (int i = 1; i <= n; i++)
        {
            if (!vis[a[i]])
            {
                b[pos] = a[i];
                vis[a[i]] = pos;
                pos = pos + 1;
            }

            node tmp;
            tmp.pos = vis[a[i]];
            tmp.dis = nxt[i];
            tmp.v = a[i];
            q.push(tmp);

            if (pos > m)
            {
                j = i;
                break;
            }
        }
        if (pos <= m)  //没填满,直接输出答案
        {
            if (m > 0) printf("%d",b[1]);
            for (int i = 2; i < pos; i++)
            {
                printf(" %d",b[i]);
            }
            printf("\n");
            continue;
        }
        //处理替换的情况
        for (int i = j + 1; i <= n; i++)
        {

            if (!vis[a[i]])
            {
                //取出b数组中,最远出现的位置
                node top = q.top();
                q.pop();
                vis[top.v] = 0;

                b[top.pos] = a[i];
                vis[a[i]] = top.pos;
            }
            //不管这个值有没有替换,都将其替换
            //之前如果是vis[a[i]],直接continue掉,不对,因为,距离需要更新
            node tmp;
            tmp.pos = vis[a[i]];
            tmp.dis = nxt[i];
            tmp.v = a[i];
            q.push(tmp);
        }
        if (m > 0) printf("%d",b[1]);
        for (int i = 2; i <= m; i++)
        {
            printf(" %d",b[i]);
        }
        printf("\n");
    }

    return 0;
}
作者:loy_184548 发表于2017/3/22 0:08:30 原文链接
阅读:54 评论:0 查看评论

ZSTU-4273-玩具【RMQ】

$
0
0

Description
商店有n个玩具,第i个玩具有价格a[i]和快乐值b[i]。有一天,小王来到商店想买一些玩具,商店老板告诉他,如果他买的所有玩具的位置是连续的,那么老板答应小王购买的所有玩具中某一个可以免费。小王接受老板的提议,他现在有零花钱k可以用来买玩具,那么他能获得的最大的快乐值是多少。
Input
第一行给测试总数T(T <= 100),接下来有T组测试数据。
每组测试数据第一行有两个数字n(1 <= n <= 5000)和k(0 <= k <= 1000000000)。
第二行有n个数字,第i个数字表示第i个玩具的价格a[i](1 <= a[i] <= 1000000)。
第三行有n个数字,第i个数字表示第i个玩具的快乐值b[i](1 <= b[i] <= 1000000)。

Output
每组测试输出小王能获得的最大快乐值。

Sample Input
3
5 14
1 2 3 4 5
5 4 3 2 1
3 1
100 1000 10000
100 1000 10000
1 0
1000000
1000000

Sample Output
15
10000
1000000

题目链接:ZSTU-4273

题目思路:套用RMQ求区间最大值即可

以下是代码:

int dp[5005][5005];
int a[5005];
int b[5005];
int n,w;
void RMQ_init()
{
    for(int i=1; i<=n; i++) dp[i][0]=a[i];
    for(int j=1; (1<<j)<=n; j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int RMQ(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    return max(dp[L][k],dp[R-(1<<k)+1][k]);
}

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        scanf("%d%d",&n,&w);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
        }
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&b[i]);
        }
        RMQ_init();
        int l = 1,sum = 0,val = 0,ans = 0;
        for (int i = 1; i <= n; i++)
        {
            int tmp = sum + a[i] - RMQ(l,i);
            if (tmp <= w)
            {
                sum += a[i];
                val += b[i];
                ans = max(ans,val);
            }
            else
            {
                sum -= a[l];
                val -= b[l];
                l++;
                i--;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
作者:loy_184548 发表于2017/3/22 0:13:29 原文链接
阅读:41 评论:0 查看评论

Codeforces Round #400 (Div. 1 + Div. 2, combined) B. Sherlock and his girlfriend 素数筛法+贪心

$
0
0

B. Sherlock and his girlfriend
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Sherlock has a new girlfriend (so unlike him!). Valentine's day is coming and he wants to gift her some jewelry.

He bought n pieces of jewelry. The i-th piece has price equal to i + 1, that is, the prices of the jewelry are 2, 3, 4, ... n + 1.

Watson gave Sherlock a challenge to color these jewelry pieces such that two pieces don't have the same color if the price of one piece is a prime divisor of the price of the other piece. Also, Watson asked him to minimize the number of different colors used.

Help Sherlock complete this trivial task.

Input

The only line contains single integer n (1 ≤ n ≤ 100000) — the number of jewelry pieces.

Output

The first line of output should contain a single integer k, the minimum number of colors that can be used to color the pieces of jewelry with the given constraints.

The next line should consist of n space-separated integers (between 1 and k) that specify the color of each piece in the order of increasing price.

If there are multiple ways to color the pieces using k colors, you can output any of them.

Examples
input
3
output
2
1 1 2 
input
4
output
2
2 1 1 2
Note

In the first input, the colors for first, second and third pieces of jewelry having respective prices 23 and 4 are 11 and 2 respectively.

In this case, as 2 is a prime divisor of 4, colors of jewelry having prices 2 and 4 must be distinct.



Source

ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined)


My Solution

题意:给出一个n,表示有2、3、......n+1这n个数,要求给这些数涂色,如果一个数是另一个数的质因数则必须涂不同的颜色。


素数筛法+贪心

首先其实只有2种数,一种是素数,一种是以这个素数作为其其中一个因数的数,所以最多用2中颜色。

用素数的O(nlogn)的筛法,边筛素数边涂色,如果i是素数,则涂1,然后对于i*j,(i*j<= n+1)涂上2.,并标记为非素数。

复杂度 O(nlogn)


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const LL MAXN = 1e5 + 8;

LL v[MAXN];
bool f[MAXN];

int main()
{
    #ifdef LOCAL
    freopen("b.txt", "r", stdin);
    //freopen("b.out", "w", stdout);
    LL T = 4;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);

    memset(f,  true, sizeof f);
    LL n, k = 1, i, j, ptr;
    cin >> n;
    for(i = 2; i <= n + 1; i++){
        ptr = 1;
        if(f[i]){
            v[i] = ptr;

            for(j = i * i; j <= n + 1; j += i){
                f[j] = false;
                if(!v[j]) {ptr = 2; v[j] = ptr;}
            }
            k = max(k, ptr);
        }
    }
    cout << k << "\n" << v[2];
    for(i = 3; i <= n + 1; i++) cout << " " << v[i];


    #ifdef LOCAL
    memset(v, 0, sizeof v);
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



Thank you!

                                                                                                                                             ------from ProLights

作者:ProLightsfxjh 发表于2017/3/22 0:49:13 原文链接
阅读:46 评论:0 查看评论

Codeforces Round #400 (Div. 1 + Div. 2, combined) C. Molly's Chemicals 区间和、构造、前缀的后缀

$
0
0

C. Molly's Chemicals
time limit per test
2.5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Molly Hooper has n different kinds of chemicals arranged in a line. Each of the chemicals has an affection value, The i-th of them has affection value ai.

Molly wants Sherlock to fall in love with her. She intends to do this by mixing a contiguous segment of chemicals together to make a love potion with total affection value as a non-negative integer power of k. Total affection value of a continuous segment of chemicals is the sum of affection values of each chemical in that segment.

Help her to do so in finding the total number of such segments.

Input

The first line of input contains two integers, n and k, the number of chemicals and the number, such that the total affection value is a non-negative power of this number k. (1 ≤ n ≤ 1051 ≤ |k| ≤ 10).

Next line contains n integers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — affection values of chemicals.

Output

Output a single integer — the number of valid segments.

Examples
input
4 2
2 2 2 2
output
8
input
4 -3
3 -6 -3 12
output
3
Note

Do keep in mind that k0 = 1.

In the first sample, Molly can get following different affection values:

  • 2: segments [1, 1][2, 2][3, 3][4, 4];

  • 4: segments [1, 2][2, 3][3, 4];

  • 6: segments [1, 3][2, 4];

  • 8: segments [1, 4].

Out of these, 24 and 8 are powers of k = 2. Therefore, the answer is 8.

In the second sample, Molly can choose segments [1, 2][3, 3][3, 4].




Source

ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined)


My Solution

题意:给出n个数字,要求选出一段连续的数字,使它的和为k的非负整数次方,为这样的区间有多少个。


区间和、构造、前缀的后缀

这是一个很有趣的构造题,一个连续区间[a, b],转化为 [1, b] - [1,a-1],如果差值,满足要求则这样的区间存在,

然后换过来,对于每个k^j,对于 [1,b] - k^j == [1,ax-1],有多少个前缀和sum{[1,ax-1]}就有多少个多少个区间[ax, b] == k^j次。

这里可以借助map来记录 前缀和sum{[1,ax-1]} 出现的次数。

此外要处理2种特殊的情况,一种是k == -1,这时pow_k[j] 只对 -1和1进行讨论, 还有一种是 k == 1,这时pow_k[j]只对 1 进行讨论。

从而巧妙的把这个问题从O(n^2)优化到了O(n)

复杂度 O(n)


#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> ii;
const int MAXN = 1e5 + 8;
const LL INF = 1e14 + 8;

map<LL, LL> mp;
LL a[MAXN], pow_k[66];

int main()
{
    #ifdef LOCAL
    freopen("c.txt", "r", stdin);
    //freopen("c.out", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);

    LL n, k, cnt, i, j, ans = 0, sum = 0;
    cin >> n >> k;
    for(i = 1; i <= n; i++) cin >> a[i];
    if(k == 1){cnt = 1; pow_k[0] = 1;}
    else if(k == -1){cnt = 2; pow_k[0] = 1; pow_k[1] = -1;}
    else{
        pow_k[0] = 1;
        for(i = 1; i < 66; i++){
            if(abs(pow_k[i-1]*k) >= INF){cnt = i; break;}
            pow_k[i] = pow_k[i-1] * k;
        }
    }
    mp[sum]++;
    for(i = 1; i <= n; i++){
        sum += a[i];
        for(j = 0; j < cnt; j++){
            ans += mp[sum - pow_k[j]];
        }
        mp[sum]++;
    }
    cout << ans << endl;

    #ifdef LOCAL
    mp.clear();
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



Thank you!

                                                                                                                                             ------from ProLights

作者:ProLightsfxjh 发表于2017/3/22 1:11:31 原文链接
阅读:47 评论:0 查看评论

Codeforces Round #400 (Div. 1 + Div. 2, combined) D. The Door Problem 2-SAT、并查集

$
0
0

D. The Door Problem
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Moriarty has trapped n people in n distinct rooms in a hotel. Some rooms are locked, others are unlocked. But, there is a condition that the people in the hotel can only escape when all the doors are unlocked at the same time. There are m switches. Each switch control doors of some rooms, but each door is controlled by exactly two switches.

You are given the initial configuration of the doors. Toggling any switch, that is, turning it ON when it is OFF, or turning it OFF when it is ON, toggles the condition of the doors that this switch controls. Say, we toggled switch 1, which was connected to room 12 and 3 which were respectively locked, unlocked and unlocked. Then, after toggling the switch, they become unlocked, locked and locked.

You need to tell Sherlock, if there exists a way to unlock all doors at the same time.

Input

First line of input contains two integers n and m (2 ≤ n ≤ 1052 ≤ m ≤ 105) — the number of rooms and the number of switches.

Next line contains n space-separated integers r1, r2, ..., rn (0 ≤ ri ≤ 1) which tell the status of room doors. The i-th room is locked ifri = 0, otherwise it is unlocked.

The i-th of next m lines contains an integer xi (0 ≤ xi ≤ n) followed by xi distinct integers separated by space, denoting the number of rooms controlled by the i-th switch followed by the room numbers that this switch controls. It is guaranteed that the room numbers are in the range from 1 to n. It is guaranteed that each door is controlled by exactly two switches.

Output

Output "YES" without quotes, if it is possible to open all doors at the same time, otherwise output "NO" without quotes.

Examples
input
3 3
1 0 1
2 1 3
2 1 2
2 2 3
output
NO
input
3 3
1 0 1
3 1 2 3
1 2
2 1 3
output
YES
input
3 3
1 0 1
3 1 2 3
2 1 2
1 3
output
NO
Note

In the second example input, the initial statuses of the doors are [1, 0, 1] (0 means locked, 1 — unlocked).

After toggling switch 3, we get [0, 0, 0] that means all doors are locked.

Then, after toggling switch 1, we get [1, 1, 1] that means all doors are unlocked.

It can be seen that for the first and for the third example inputs it is not possible to make all doors unlocked.



Source

ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined)


My Solution

题意:每个门有且必须被2个开关所控制,一个开关可以控制多个门,给定n个门的初始状态和每个开关控制哪些门,问是否有方案打开一些开关使所有的门都为unlocked状态。


2-SAT、并查集

把由于每个门被2个开关控制,所以把门看成是边,把开关看成是点,每个开关有2种点,打开i和关闭i+m,从而变成一个经典的 2-SAT 问题。

一个门分别被last[r] 和 i控制,则

如果门是开的,则2个开关要么都关要么都开,_merge(last[r], i);  _merge(last[r] + m, i + m);

否则只开其中一个,_merge(last[r], i + m); _merge(last[r] + m, i);

最后扫一遍并查集,如果 存在至少一个开关的点 i 和 i+m处在同一颗树上,则开关即开有关,相矛盾,故不存在可行方案,

否则存在。

复杂度 O(2*n)


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 8;

int father[2*MAXN], _rank[2*MAXN];
inline void init(int n)
{
    for(int i = 0; i <= n; i++){
        father[i] = i;
        _rank[i] = 0;
    }
}
inline int _find(int x)
{
    return father[x] = father[x] == x ? x : _find(father[x]);
}
inline void _merge(int x, int y)
{
    int a = _find(x), b = _find(y);
    if(a == b) return;
    else{
        if(_rank[a] < _rank[b]){
            father[a] = b;
        }
        else{
            father[b] = a;
            if(_rank[a] == _rank[b]){
                _rank[a]++;
            }
        }
    }

}

bool unlocked[MAXN];
int last[MAXN];

int main()
{
    #ifdef LOCAL
    freopen("d.txt", "r", stdin);
    //freopen("d.out", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);

    int n, m, i, j, x, r;
    cin >> n >> m;
    init(2*m);
    for(i = 1; i <= n; i++){
        cin >> unlocked[i];
    }
    for(i = 1; i <= m; i++){
        cin >> x;
        for(j = 1; j <= x; j++){
            cin >> r;
            if(last[r] == 0) last[r] = i;
            else{
                if(unlocked[r]){
                    _merge(last[r], i);
                    _merge(last[r] + m, i + m);
                }
                else{
                    _merge(last[r], i + m);
                    _merge(last[r] + m, i);
                }
            }
        }
    }
    bool ans = true;
    for(i = 1; i <= m; i++){
        if(_find(i) == _find(i + m)){
            ans = false;
            break;
        }
    }
    if(ans) cout << "YES" << endl;
    else cout << "NO" << endl;


    #ifdef LOCAL
    memset(last, 0, sizeof last);
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}



Thank you!

                                                                                                                                             ------from ProLights

作者:ProLightsfxjh 发表于2017/3/22 1:26:12 原文链接
阅读:42 评论:0 查看评论

Mycat高级进阶---Mycat注解

$
0
0

注解原理

概念:
MyCat对自身不支持的Sql语句提供了一种解决方案——在要执行的SQL语句前添加额外的一段由注解SQL组织的代码,这样Sql就能正确执行,这段代码称之为“注解”。注解的使用相当于对mycat不支持的sql语句做了一层透明代理转发,直接交给目标的数据节点进行sql语句执行,其中注解SQL用于确定最终执行SQL的数据节点。注解的形式是:

/*!mycat: sql=注解Sql语句*/

注解的使用方式是:

/*!mycat: sql=注解Sql语句*/真正执行Sql

使用时将=号后的“注解Sql语句”替换为需要的Sql语句即可,后面会提到具体的用法。
原理:
MyCat执行SQL语句的流程是先进行SQL解析处理,解析出分片信息(路由信息)后,然后到该分片对应的物理库上去执行;若传入的SQL语句MyCat无法解析,则MyCat不会去执行;而注解则是告诉MyCat按照注解内的SQL(称之为注解SQL)去进行解析处理,解析出分片信息后,将注解后真正要执行的SQL语句(称之为原始SQL)发送到该分片对应的物理库上去执行。
从上面的原理可以看到,注解只是告诉MyCat到何处去执行原始SQL;因而使用注解前,要清楚的知道该原始SQL去哪个分片执行,然后在注解SQL中也指向该分片,这样才能使用!例子中的sharding_id=10010 即是指明分片信息的。
需要说明的是,若注解SQL没有能明确到具体某个分片,譬如例子中的注解SQL没有添加sharding_id=10010这个条件,则MyCat会将原始SQL发送到persons表所在的所有分片上去执行去,这样造成的后果若是插入语句,则在多个分片上都存在重复记录,同样查询、更新、删除操作也会得到错误的结果!
解决问题:


    • MySql不支持的语法结构,如insert …select…
  • 同一个实例内的跨库关联查询,如用户库和平台库内的表关联
  • 存储过程调用。
  • 表,存储过程创建。
    注解规范
  • 注解SQL使用select语句,不允许使用delete/update/insert等语句;虽然delete/update/insert 等语句也能用在注解中,但这些语句在Sql处理中有额外的逻辑判断,从性能考虑,请使用select语句
  • 注解SQL禁用表关联语句
  • 注解SQL尽量用最简单的SQL语句,如select id from tab_a where id=’10000’
  • 无论是原始SQL还是注解SQL,禁止DDL语句
  • 能不用注解的尽量不用
  • 详细要求见下面
    Select
    -选择能唯一确定分片的主表,如与用户表关联的时候可以选择用户表
  • 若是业务需要在主表所在的各个分片上都执行可以不加能确定分片的条件
    Insert
    对于分片表
  • 使用insert的表做注解SQL
  • 注解SQL必须能确认具体到某个分片
  • 原始SQL插入的字段必须包含分片字段
  • 原始SQL中包含的分片字段和注解SQL中的分片字段确定的分片务必要一致
  • 对于insert … select这种语句,请务必确认插入的记录都在当前查找到的分片上
    非分片表
  • 注解SQL必须能具体确认到某个分片
  • 注解SQL包含的分片字段其分片上必须包含这个非分片表
    Delete
  • 对于分片表使用要删除记录的表做注解SQL
    Update
  • 对于分片表用所要更新的表做注解SQL
  • 禁止更新分片表的分片列
  • 根据业务需要添加注解Sql的分片字段值
    Call
  • 若是要在所有的分片上都执行存储过程,则使用一个在所有分片上都包含的表,不添加任何分片条件 调用存储过程
  • 若是单个分片执行,使用能确认到这个分片的表以及分片条件
    补充说明:
    使用注解并不额外增加MyCat的执行时间;从解析复杂度以及性能考虑,注解SQL应尽量简单。至于一个SQL使用注解和不使用注解的性能对比,不存在参考意义,因为前提是MyCat不支持的SQL才使用注解。

注解使用示例

注解支持的’!’不被mysql单库兼容,
注解支持的’#’不被mybatis兼容
新增加mycat字符前缀标志Hintsql:”/* mycat: /”
从1.6开始支持三种注解方式:

/*#mycat:db_type=master*/ select * from travelrecord /*!mycat:db_type=slave*/ select * from travelrecord /**mycat:db_type=master*/ select * from travelrecord

Mycat端执行存储创建表或存储过程为:
存储过程:

/*!mycat: sql=select 1 from test */ CREATE PROCEDURE `test_proc`() BEGIN END ;

表:

 /*!mycat: sql=select 1 from test */create table test2(id int);

注意注解中语句是节点的表请替换成自己表如select 1 from 表 ,注解内语句查出来的数据在哪个分片,数据在那个节点往哪个节点建.
特殊语句自定义分片:

 /*!mycat: sql=select 1 from test */insert into t_user(id,name) select id,name from t_user2;

读写分离
配置了Mycat读写分离后,默认查询都会从读节点获取数据,但是有些场景需要获取实时数据,如果从读节点获取数据可能因延时而无法实现实时,Mycat支持通过注解/balance/来强制从写节点查询数据:

a. 事务内的SQL,默认走写节点,以注解/*balance*/开头,则会根据schema.xml的dataHost标签属性的balance=“1”或“2”去获取节点 
b. 非事务内的SQL,开启读写分离默认根据balance=“1”或“2”去获取,以注解/*balance*/开头则会走写节点解决部分已经开启读写分离,但是需要强一致性数据实时获取的场景走写节点
 /*balance*/ select a.* from customer a where a.company_id=1;

多表

 ShareJoin /*!mycat:catlet=demo.catlets.ShareJoin */ select a.*,b.id, b.name as tit from customer a,company b on a.company_id=b.id;

读写分离数据源选择

/*!mycat:db_type=master*/ select * from travelrecord /*!mycat:db_type=slave*/ select * from travelrecord /*#mycat:db_type=master*/ select * from travelrecord /*#mycat:db_type=slave*/ select * from travelrecord

多租户支持
通过注解方式在配置多个schema情况下,指定走哪个配置的schema。
web部分修改: a.在用户登录时,在线程变量(ThreadLocal)中记录租户的id b.修改jdbc的实现:在提交sql时,从ThreadLocal中获取租户id, 添加sql 注释,把租户的schema 放到注释中。例如:/!mycat : schema = test_01 / sql ;
在db前面建立proxy层,代理所有web过来的数据库请求。proxy层是用mycat实现的,web提交的sql过来时在注释中指定schema, proxy层根据指定的schema转发sql请求。

 /*!mycat : schema = test_01 */ sql ;
作者:wangshuang1631 发表于2017/3/22 20:08:34 原文链接
阅读:70 评论:0 查看评论

GYM-100952-Special Palindrome【动态规划】

$
0
0

这里写图片描述

题目大意:定义特殊回文串,例如:abcdcba(a <= b <= c <= d)
给出n,问:a+b+c+d+c+b+a的值为n的回文串的方法数有多少?

题目思路:

dp[i][j] //表示值为i,以j开头的方法数有多少

以下是代码:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <functional>
#include <numeric>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <deque>
#include <list>

using namespace std;
long long  dp[500][500];
long long ans[500];
void init()
{
    dp[0][1] = 1;
    dp[1][1] = 1;
    dp[2][1] = 1;dp[2][2] = 1;
    dp[3][1] = 1;dp[3][3] = 1;
    ans[1] = 1;ans[2] = 2;ans[3] = 2;

    for (int i = 4; i <= 250; i++)
    {
        long long tmp = 0;
        for (int j = 1; j <= i / 2; j++)
        {
            if (j == 1) dp[i][j] = ans[i - 2];
            else
            {
                long long u = i - j * 2;
                if (u == 0)
                {
                    dp[i][j] = 1;
                }
                else
                {
                    long long ret = 0;
                    for (int k = j; k <= u; k++)
                    {
                        ret += dp[u][k];
                    }
                    dp[i][j] = ret;
                }
            }
            tmp += dp[i][j];

        }
        dp[i][i] = 1;
        tmp += 1;
        ans[i] = tmp;
    }

}
int main()
{
    int n;
    init();
    while(cin >> n)
    {
        if (n == 0) break;
        cout << ans[n] << endl;
    }
    return 0;
}
作者:loy_184548 发表于2017/3/22 20:10:55 原文链接
阅读:62 评论:0 查看评论

Mycat高级进阶---MyCAT支持的Catlet实现

$
0
0

通过catlet支持跨分片复杂SQL实现以及存储过程支持等。使用方式主要通过mycat注释的方式来执行,如下:
1. 跨分片联合查询注解支持:

/*!mycat:catlet=demo.catlets.ShareJoin / select bu.,sg.* from base_user bu,sam_glucose sg where bu.id_=sg.user_id;

注:sam_glucose 是跨分片表;
2. 存储过程注解支持:

/*!mycat: sql=select * from base_user where id_=1;*/ CALL proc_test();

注:目前执行存储过程通过mycat注解的方式执行,注意需要把存储过程中的sql写到注解中;
3. 批量插入与ID自增长结合的支持:

/*!mycat:catlet=demo.catlets.BatchInsertSequence */ insert into sam_test(name_) values(‘t1’),(‘t2’);

注: 此方式不需要在sql语句中显示的设置主键字段,程序在后台根据primaryKey配置的主键列,自动生成主键的sequence值并替换原sql中相关的列和值;
4. 获取批量sequence值的支持:

/*!mycat:catlet=demo.catlets.BatchGetSequence */SELECT mycat_get_seq(‘MYCAT_TEST’,100);

注:此方法表示获取MYCAT_TEST表的100个sequence值,例如当前MYCAT_TEST表的最大sequence值为5000,则通过此方式返回的是5001,同时更新数据库中的MYCAT_TEST表的最大sequence值为5100.

作者:wangshuang1631 发表于2017/3/22 20:11:16 原文链接
阅读:67 评论:0 查看评论

【Arch】Android 7 Nougat源码目录结构分析

$
0
0
|-  art // Android Runtime,一种App运行模式,区别于传统的Dalvik虚拟机,旨在提高Android系统的流畅性,包括以下几个目录。            
    |-  benchmark // 程序测试基准。        
    |-  build // 编译文件。      
    |-  cmdline // 命令行工具的初始化与解析。        
    |-  compiler // 编译套件。       
    |-  dalvikvm // Dalvik虚拟机启动程序。      
    |-  dex2oat // 文件dex格式转换为oat格式的转换程序。        
    |-  dexdump // 文件dex格式的内容获取程序。      
    |-  dexlayout // 文件dex格式的布局。        
    |-  dexlist // 文件dex格式的函数获取程序。      
    |-  disassembler // 几种反汇编实现,包括arm64、arm、mips和x86。       
    |-  imgdiag // image诊断程序。       
    |-  libart_fake // 一个虚假的art库,用于那些企图链接ark库的作弊程序。     
    |-  oatdump // 文件oat格式的内容获取程序。      
    |-  patchoat // 文件oat格式的补丁管理程序。     
    |-  profman // 程序性能分析助手。        
    |-  runtime // art库实现,主要为C++和汇编文件。      
    |-  sigchainlib // 信号处理库。       
    |-  test // 测试程序。       
    |-  tools // 一些工具,包括python和shell脚本。     
|-  bionic // Android改造的C/C++库,包括以下几个目录。            
    |-  benchmarks // 程序测试基准。       
    |-  build // 编译文件。      
    |-  libc // libc        
    |-  libdl // libdl      
    |-  libm // libm        
    |-  libstdc++ // libstdc++      
    |-  linker // 程序链接器。        
    |-  tests // 测试程序。      
    |-  tools // 一些工具,包括python和shell脚本。     
|-  bootable // Android程序启动导引,包括一个recovery目录。           
    |-  recovery // 系统还原。       
|-  build // Android编译系统,包括原有的GNU make/mk和新加入的go/bp,包括以下几个目录。           
    |-  blueprint // 编译系统组件,由go实现,用于读取类json格式的bp文件,转换成Ninja格式。      
    |-  kati // 编译系统组件,用于兼容原有的GNU make/mk,对mk文件进行格式转换。      
    |-  make // 原有的编译系统实现,包括makefile、python、shell等。     
    |-  soong // 编译系统组件,同样是辅助生成Ninja格式的文件。      
|-  compatibility // Android软、硬件的兼容性规则,包括一个cdd目录。           
    |-  cdd // Compatibility Defination Document,为markdown语法,包括以下13项内容。     
        |-  1_introduction  
        |-  2_device-types  
        |-  3_software  
        |-  4_application-packaging 
        |-  5_multimedia    
        |-  6_dev-tools-and-options 
        |-  7_hardware-compatibility    
        |-  8_performance-and-power 
        |-  9_security-model    
        |-  10_software-compatibility-testing   
        |-  11_updatable-software   
        |-  12_document-changelog   
        |-  13_contact-us   
|-  cts // Android Compatibility Test Suite,需符合cdd的要求,包括以下几个目录。         
    |-  apps        
    |-  build       
    |-  common      
    |-  development     
    |-  hostsidetests       
    |-  libs        
    |-  suite       
    |-  tests       
    |-  tools       
|-  dalvik // Android Dalvik虚拟机相关内容,包括以下几个目录。           
    |-  dexdump     
    |-  dexgen      
    |-  docs        
    |-  dx      
    |-  libdex      
    |-  opcode-gen      
    |-  tools       
|-  developers // Android开发者参考文档,包括以下几个目录。          
    |-  build // gradle编译系统。        
    |-  demos // 使用了gradle的例子。      
    |-  samples // Android SDK中的例子。     
|-  development // Android开发基础设施,包括以下几个目录。          
    |-  apps // 若干app。      
    |-  build // 编译文件,包括打包用的atree文件。        
    |-  cmds // 工具monkey。       
    |-  docs // 说明文档。       
    |-  host // host        
    |-  ide // ide,包括eclipse、emacs和intellij。        
    |-  libraries // lib库。      
    |-  ndk // ndk      
    |-  python-packages // python工具包,包括adb、fastboot和gdbrunner。      
    |-  samples // 示例代码。        
    |-  scripts // python、shell脚本。      
    |-  sdk // sdk      
    |-  sdk_overlay // sdk overlay      
    |-  sys-img // 系统镜像信息。      
    |-  testrunner // 测试程序启动脚本。     
    |-  tools // 一些常用的工具,如make_key等 。       
    |-  tutorials // 教程。        
|-  device // Android支持的各种设备及相关配置,结构相似,包括以下几个目录。            
    |-  asus // 华硕      
    |-  common // 设备间共有的配置。     
    |-  generic // 不同的CPU架构,包括arm、goldfish、emulator、mips、x86等。      
    |-  google // 谷歌        
    |-  htc // htc      
    |-  huawei // 华为        
    |-  lge // LG       
    |-  linaro // Linario       
    |-  moto // 摩托罗拉        
    |-  sample // 例子        
|-  docs // Android系统介绍,包括一个source.android.com目录。           
    |-  source.android.com // AOSP,Android Open Source Project。     
|-  external // Android中使用的外部开源库,包括以下几个目录。          
    |-  aac // Advanced Audio Coding,高级音频编码。        
    |-  abi-compliance-checker // ABI兼容性分析工具。       
    |-  abi-dumper // ABI数据解析工具。        
    |-  android-clat // Android中用NAT64/DNS64支持IPv4的程序运行于IPv6的网络。        
    |-  androidplot // Android中用以创建动态的或静态的图表。       
    |-  ant-glob // ANT模式匹配工具。      
    |-  antlr // Language Recognition,一款语法分析器,可根据输入自动生成语法树并显示出来。        
    |-  apache-commons-math // Apache数学库。       
    |-  apache-harmony // Apache Java SE运行时类库及一些工具。     
    |-  apache-http // Apache HTTP服务。       
    |-  apache-xml // Apache XML解决方案。       
    |-  archive-patcher // 补丁管理库。       
    |-  autotest // 自动测试框架,Python实现,起初用于Linux Kernel,后扩展到Chrome OS和Android。     
    |-  avahi // Zeroconf规范的一种实现,可以在本地网络中发布和获知各种服务和主机。      
    |-  avb // Ethernet Audio/Video Bridging,以太网音视频桥接技术。        
    |-  bison // 语法分析器生成器。      
    |-  blktrace // 收集磁盘IO信息中当IO进行到块设备层即block设备时的详细信息。      
    |-  boringssl // BoringSSL为OpenSSL的一个分支,优化了一些加密算法。      
    |-  bouncycastle // 加解密包。       
    |-  bsdiff // 二进制增量分析工具,生成新、旧版本的一个patch,用以旧版本增量升级到新版本。      
    |-  bzip2 // 基于Burrows-Wheeler算法的无损压缩技术。        
    |-  caliper // 基准测量工具。      
    |-  c-ares // DNS请求异步处理库。       
    |-  cblas // C interface to Legacy BLAS。        
    |-  ceres-solver // c++库,用于建模、解决复杂的非线性最小二乘问题,如3D模型、计算机视觉等。      
    |-  chromium-libpac // 基于proxy_resolver_v8。     
    |-  chromium-trace // 以HTML的形式显示数据使用情况。     
    |-  chromium-webview // Webview。        
    |-  clang // 编译器。       
    |-  cmockery // 用于C程序的单元测试。     
    |-  compiler-rt // Compiler Routine。        
    |-  conscrypt // A Java Security Provider。      
    |-  crcalc // Constructive Real Calculator。     
    |-  cros // 一些常量和定义,只有一些头文件和proto文件。        
    |-  curl // 文件传输。       
    |-  dagger2 // A fast dependency injector for Android and Java。     
    |-  dbus // dbus。       
    |-  dbus-binding-generator // dbus bind。        
    |-  deqp // GPU测试框架。        
    |-  dexmaker // dex maker。      
    |-  dhcpcd-6.8.2 // DHCP client daemon。     
    |-  dlmalloc // malloc/free routines implemented by Doug Lea。       
    |-  dng_sdk // DNG文件读写库。        
    |-  dnsmasq // 配置DNS和DHCP的工具。       
    |-  doclava // Javadoc工具。       
    |-  donuts // donut。        
    |-  drm_gralloc // gralloc for drm,Direct Rendering Manager。        
    |-  drm_hwcomposer // hwcompositor for drm。     
    |-  droiddriver // Android UI testing library。      
    |-  dtc // Device Tree Compiler。        
    |-  e2fsprogs // 文件系统工具集。       
    |-  easymock // 单元测试模拟框架。       
    |-  eclipse-basebuilder // eclipe插件编译相关。        
    |-  eclipse-windowbuilder // eclipse编译相关。       
    |-  eigen // 用于线性代数的C++模板库。     
    |-  elfutils // ELF     
    |-  emma // 单元测试覆盖率统计。      
    |-  esd // 音频相关。        
    |-  expat // XML解析。     
    |-  eyes-free // 语音交互。      
    |-  f2fs-tools // Flash Friendly File System。       
    |-  fdlibm // Freely Distributed LIBM,数学库。      
    |-  fec // Forward error correction。        
    |-  fio / io测试工具。       
    |-  flac // Free Lossless Audio Codec。      
    |-  fmtlib // format。       
    |-  fonttools // 字体处理工具。        
    |-  freetype // 字体引擎。       
    |-  fsck_msdos // 文件系统检查工具。     
    |-  gemmlowp // low-precision for general matrix multiplication。        
    |-  giflib // gif图片库。       
    |-  glide // media管理框架。     
    |-  google-benchmark // 支持benchmark的库,类似于单元测试。      
    |-  google-breakpad // crash报告系统,包括client、server。       
    |-  google-fonts // 字体。         
    |-  googletest // C++ test framework。       
    |-  google-tv-pairing-protocol // tv配对协议。       
    |-  gptfdisk // 文本模式的磁盘分区工具。        
    |-  guava // Google Core Libraries for Java。        
    |-  guice // 依赖注入框架。        
    |-  hamcrest // 用于测试的可以合成各种表达式的匹配器类库。       
    |-  harfbuzz_ng // 字体排版引擎。      
    |-  hyphenation-patterns // 各种语言的字体连接模式。        
    |-  icu // Unicode组件。       
    |-  ImageMagick // bitmap图片管理,支持多种格式。       
    |-  ims // IP Multi-media System,包括rcs融合通信。     
    |-  iproute2 // 网络配置工具包。        
    |-  ipsec-tools // 加密的ip协议工具包。      
    |-  iptables // IP信息包过滤系统。      
    |-  iputils // 网络工具包。       
    |-  iw // Netlink 802.11。       
    |-  jacoco // 测试覆盖率工具。      
    |-  jarjar // Java包管理工具。        
    |-  javasqlite // sqlite        
    |-  javassist // Java字节码编辑。     
    |-  jcommander // 参数解析。     
    |-  jdiff // Java代码比较工具。        
    |-  jemalloc // 更好的内存管理工具,解决内存碎片问题。     
    |-  jetty // servlet容器。     
    |-  jline // 处理控制台输入。       
    |-  jmdns // 多播DNS实现,可在本地局域网中发现和注册服务。       
    |-  jsilver // HTML模板系统。        
    |-  jsmn // JSON解析。     
    |-  jsoncpp // C++处理JSON,序列化和反序列化。      
    |-  jsr305 // Java Specification Request。       
    |-  jsr330 // Java Specification Request。       
    |-  junit // Java单元测试框架。        
    |-  junit-params // jnit升级版,添加了更好用的参数化测试。       
    |-  kernel-headers // Kernel级别头文件。      
    |-  ksoap2 // 访问Web Service。        
    |-  libavc      
    |-  libbrillo       
    |-  libcap      
    |-  libcap-ng       
    |-  libchrome       
    |-  libconstrainedcrypto        
    |-  libcups     
    |-  libcxx      
    |-  libcxxabi       
    |-  libdaemon       
    |-  libdivsufsort       
    |-  libdrm      
    |-  libedit     
    |-  libevent        
    |-  libexif     
    |-  libgdx      
    |-  libgsm      
    |-  libhevc     
    |-  libjpeg-turbo       
    |-  libldac     
    |-  liblzf      
    |-  libmicrohttpd       
    |-  libmojo     
    |-  libmpeg2        
    |-  libmtp      
    |-  libnl       
    |-  libogg      
    |-  libopus     
    |-  libpcap     
    |-  libphonenumber      
    |-  libpng      
    |-  libunwind       
    |-  libunwind_llvm      
    |-  libusb      
    |-  libusb-compat       
    |-  libutf      
    |-  libvncserver        
    |-  libvorbis       
    |-  libvpx      
    |-  libvterm        
    |-  libweave        
    |-  libxml2     
    |-  libyuv      
    |-  linux-kselftest // linux test。      
    |-  littlemock // mock框架。       
    |-  lld // LLVM linker。         
    |-  llvm // Low Level Virtual Machine。      
    |-  ltp // Linux Test Project。      
    |-  lz4 // 快速的无损压缩算法。       
    |-  lzma // 压缩。     
    |-  markdown // Markdown,一种标记语言。        
    |-  mdnsresponder // Appple Bonjour组件,方便IP网络配置。     
    |-  mesa3d // 三维计算机图形库。     
    |-  messageformat // International Components for Unicode for Java。     
    |-  Microsoft-GSL // Guideline Support Library。     
    |-  minijail // 沙盒,运行不信任的程序。        
    |-  mksh // MirBSD Korn Shell。      
    |-  mmc-utils // mmc卡管理。        
    |-  mockftpserver // 模拟FTP服务以进行FTP客户端测试。        
    |-  mockito // 测试框架。        
    |-  mockwebserver // 测试框架。      
    |-  modp_b64 // base64编码、解码。        
    |-  mp4parser // mp4解析。     
    |-  mtpd // Media Transfer Protocol。        
    |-  nanohttpd // HTTP Server,用于嵌入其它的程序。     
    |-  nanopb-c // ANSI-C实现的Protocol Buffer。       
    |-  naver-fonts // 字体。      
    |-  netcat // 网络使用查看工具。     
    |-  netperf // 网络性能测试。      
    |-  neven // 人脸识别算法。        
    |-  nfacct // 流量统计。     
    |-  nist-pkits // NIST PKI Test Suite。      
    |-  nist-sip // nist实现的sip协议,ip电话。      
    |-  noto-fonts // 汉语、日语、韩语字体。       
    |-  oauth // 关于授权的开放网络标准。       
    |-  objenesis // Java对象实例化库。        
    |-  okhttp // HTTP&SPDY Client。     
    |-  opencv // 计算机视觉库。       
    |-  opencv3 // 计算机视觉库。      
    |-  owasp // Web Application。       
    |-  parameter-framework // system-wide parameter management。        
    |-  pcre // Perl兼容的正则表达式库。      
    |-  pdfium // PDF渲染引擎。      
    |-  piex // Preview Image Extractor。        
    |-  ppp // Point to Point Protocol,链路层协议。       
    |-  proguard // Java class file shrinker, optimizer, obfuscator and preverifier.        
    |-  protobuf // 数据交互格式。     
    |-  regex-re2 // 正则表达式库。        
    |-  replicaisland // A side scrolling video game for Android。       
    |-  rmi4utils // Remote Method Invoke。      
    |-  robolectric // 黑盒测试。        
    |-  roboto-fonts // roboto font。        
    |-  rootdev // Chromium OS version of rootdev。      
    |-  safe-iop // safe integer operation。     
    |-  scrypt // 加密相关。     
    |-  seccomp-tests // Seccomp-BPF Kernel Self-Test Suite。        
    |-  selinux // Secure Linux。        
    |-  sfntly // 字体库。      
    |-  shflags // shell script。        
    |-  skia // 2D图形库。      
    |-  sl4a // Scripting Layer for Android。        
    |-  slf4j // Simple Logging Facade for Java。        
    |-  smali // Dalvik虚拟机的dex格式的汇编与反汇编。        
    |-  snakeyaml // 用于Java虚拟机的YAML文件解析器。       
    |-  sonic // 语音开发库。     
    |-  sonivox // 语音开发库。       
    |-  speex // 语音开发库。     
    |-  spirv-llvm // Khronos LLVM-SPIRV图形渲染语言格式转换。     
    |-  sqlite // sqlite。       
    |-  squashfs-tools // 只读的高压缩的文件系统。      
    |-  srtp // Secure Real-time Transport Protocol。        
    |-  strace // system call tracer。       
    |-  svox // 语音库。        
    |-  tagsoup // SAX解析。       
    |-  tcpdump // 网络监听。        
    |-  testng // 实机测试及数据收集。        
    |-  timezonepicker-support // Time Zone。        
    |-  tinyalsa // ALSA处理。     
    |-  tinycompress // 用于ALSA格式的读取,如mp3。       
    |-  tinyxml // XML解析工具,C++实现。       
    |-  tinyxml2 // XML解析。      
    |-  tlsdate // 时间更新服务,TCP实现。        
    |-  toybox // 命令行工具包。       
    |-  tpm2 // Trusted Platform Module。        
    |-  tremolo // ogg音频解压。     
    |-  unicode // Unicode。     
    |-  universal-tween-engine // Java对象插值。     
    |-  v8 // JavaScript引擎,C++实现。       
    |-  valgrind // 内存、性能分析工具。      
    |-  vboot_reference // Chrome OS verified boot in firmware。     
    |-  vixl // ARMv8 Runtime Code Generation Library。      
    |-  vogar // vogar.     
    |-  vulkan-validation-layers // Vulkan组件,包括ICD Loader和Validation Layer。     
    |-  webp // 处理WebP格式的图片。        
    |-  webrtc // 支持浏览器、移动App的Real-time Communication。      
    |-  wpa_supplicant_8 // WIFI Protected Access。      
    |-  xmlrpcpp // XmlRpc协议的C++实现。     
    |-  xmlwriter // xml        
    |-  xmp_toolkit // xmp      
    |-  zlib // 使用了DEFLATE算法的数据压缩库。     
    |-  zopfli // C库,一种压缩算法。        
    |-  zxing // Java库,用于识别1D/2D条形码。        
|-  frameworks // Android基础框架。          
    |-  av // av,包括以下几个目录。      
        |-  camera  
        |-  cmds    
        |-  drm 
        |-  media   
        |-  radio   
        |-  services    
        |-  soundtrigger    
        |-  tools   
    |-  base // base,包括以下几个目录。      
        |-  api 
        |-  cmds    
        |-  core    
            |-  java
            |-  jni
            |-  res
            |-  tests
        |-  data    
        |-  docs    
        |-  drm 
        |-  graphics    
        |-  keystore    
        |-  legacy-test 
        |-  libs    
            |-  androidfw
            |-  common_time
            |-  hwui
            |-  input
            |-  storage
            |-  usb
        |-  location    
        |-  media   
        |-  native  
        |-  nfc-extras  
        |-  obex    
        |-  opengl  
        |-  packages    
        |-  proto   
        |-  rs  
        |-  samples 
        |-  sax 
        |-  services    
        |-  telecomm    
        |-  telephony   
        |-  test-runner 
        |-  tests   
        |-  tools   
        |-  wifi    
    |-  compile // 编译相关。        
    |-  data-binding // 数据绑定。       
    |-  ex // ex。       
    |-  minikin // Text Layout。     
    |-  ml // Machine Learning。     
    |-  multidex // Multi-dex Loader。       
    |-  native // native实现,包括以下几个目录。        
        |-  aidl    
        |-  build   
        |-  cmds    
        |-  data    
        |-  docs    
        |-  libs    
            |-  binder
            |-  diskusage
            |-  gui
            |-  input
            |-  ui
        |-  opengl  
        |-  services    
            |-  batteryservice
                inputflinger
                nativeperms
                powermanager
                sensorservice
                surfaceflinger
        |-  vulcan  
    |-  opt // 一些软件。        
    |-  rs // Render Script,可创建3D接口。        
    |-  support // support      
    |-  volley // volley        
    |-  webview // webview      
    |-  wilhelm // Wilhelm,基于Khronos的OpenSL ES/OpenMAX AL的audio/multimedia实现。       
|-  hardware // HAL层,包括以下几个目录。          
    |-  akm // AK8975传感器,包括SensorControl和HAL层的libsensors。       
    |-  broadcom // Boradcom,包括libbt和wlan。      
    |-  google // Google,包括Android Packet Filter。       
    |-  intel // Intel,包括audio、media、bootstub、img、sensor等。      
    |-  interfaces // HAL接口,包括以下几个目录。       
        |-  audio   
        |-  benchmarks  
        |-  bluetooth   
        |-  boot    
        |-  health  
        |-  ir  
        |-  light   
        |-  memtrack    
        |-  nfc 
        |-  power   
        |-  radio   
        |-  sensors 
        |-  tests   
        |-  thermal 
        |-  tv  
        |-  vehicle 
        |-  vibrator    
        |-  wifi    
    |-  invensense // InvenSense传感。     
    |-  libhardware // libhardware,包括以下几个模块。        
        |-  modules 
            |-  audio
            |-  audio_remote_submix
            |-  camera
            |-  consumerir
            |-  fingerprint
            |-  gralloc
            |-  hwcomposer
            |-  input
            |-  local_time
            |-  nfc
            |-  nfc-nci
            |-  power
            |-  radio
            |-  sensors
            |-  soundtrigger
            |-  thermal
            |-  tv_input
            |-  usbaudio
            |-  usbcamera
            |-  vehicle
            |-  vibrator
            |-  vr
    |-  libhardware_legacy // hardware legacy,包括以下几个模块。     
        |-  audio   
        |-  power   
        |-  uevent  
    |-  marvell // Marvell,包括bt。        
    |-  qcom // Qualcomm,包括audio、wlan等。     
    |-  ril // Radio Interface Layer。       
|-  kernel // Linux Kernel,不过Android默认不提供,需要单独下载,只有一个tests目录。           
    |-  tests // net测试。     
|-  libcore // Android Java核心类库,包括以下几个目录。           
    |-  benchmarks      
    |-  dalvik      
    |-  dex     
    |-  dom     
    |-  expectations        
    |-  harmony-tests       
    |-  json        
    |-  jsr166-tests        
    |-  libart      
    |-  luni        
    |-  ojluni      
    |-  support     
    |-  test-rules      
    |-  tzdata      
    |-  xml     
|-  libnativehelper // Android Java类库的native实现助手,包括一个tests目录。           
    |-  tests // 测试程序。      
|-  packages // Android Package,包括以下几个目录。           
    |-  apps // 各种app。      
    |-  experiment // 非release/public的测试程序。     
    |-  inputmethods // 输入法,包括LatinIME和OpenWnn。         
    |-  providers // 各种provider。        
    |-  screensavers // 屏保。     
    |-  services // 各种service。      
    |-  wallpapers // 壁纸。       
|-  pdk // Android Platform Development Kit,包括以下几个目录。           
    |-  apps        
    |-  build       
    |-  util        
|-  platform_testing // Android平台测试程序,包括以下几个目录。         
    |-  build       
    |-  libraries       
    |-  scripts     
    |-  tests       
    |-  utils       
|-  prebuilts // Android预编译目录,包括以下几个目录。         
    |-  android-emulator // Android模拟器,由external/qemu/android/scripts/package-release.sh生成。     
    |-  build-tools // Ninja编译系统的辅助工具。      
    |-  checkstyle // Java编码规范检查。       
    |-  clang // c/c++/object-c代码编译器。       
    |-  deqp // Draw Elements Quality Program,适用于OpenGL ES/OpenCL的GPU应用分析。      
    |-  devtools // 开发工具,如常见的adt、android、ddms、lint等。        
    |-  eclipse // eclipse。     
    |-  gcc // gcc。     
    |-  gdb // gdb。     
    |-  go // go。       
    |-  gradle-plugin // gradle插件。      
    |-  libs // libedit。        
    |-  maven_repo // maven。        
    |-  misc // misc。       
    |-  ndk // ndk。     
    |-  python // python。       
    |-  qemu-kernel // qemu kernel。         
    |-  sdk // sdk。     
    |-  tools // tool。      
|-  sdk // Android的Java层SDK,包括以下几个目录。           
    |-  annotations     
    |-  apkbuilder      
    |-  apps        
    |-  attribute_stats     
    |-  avdlauncher     
    |-  bash_completion     
    |-  build       
    |-  docs        
    |-  dumpeventlog        
    |-  eclipse     
    |-  emulator        
    |-  eventanalyzer       
    |-  files       
    |-  find_java       
    |-  find_java2      
    |-  find_lock       
    |-  hierarchyviewer     
    |-  icons       
    |-  sdklauncher     
    |-  settings        
    |-  templates       
    |-  testapps        
|-  system // Android系统设施,包括以下几个目录。         
    |-  bt // 蓝牙        
    |-  ca-certificates // Certificate Authority。       
    |-  connectivity // WIFI,包括wificond和wifilogd两个daemon。       
        |-  wificond    
        |-  wifilogd    
    |-  core // 核心库,包括以下几个目录。       
        |-  adb 
        |-  adf 
        |-  base    
        |-  bootstat    
        |-  cpio    
        |-  debuggerd   
        |-  fastboot    
        |-  fingerprintd    
        |-  fs_mgr  
        |-  gatekeeperd 
        |-  healthd 
        |-  init    
        |-  libappfuse  
        |-  libbacktrace    
        |-  libbinderwrapper    
        |-  libcrypto_utils 
        |-  libcutils   
        |-  libdiskconfig   
        |-  libion  
        |-  liblog  
        |-  libmemtrack 
        |-  libmemunreachable   
        |-  libnativebridge 
        |-  libnativeloader 
        |-  libnetutils 
        |-  libpackagelistparser    
        |-  libpixelflinger 
        |-  libprocessgroup 
        |-  libprocinfo 
        |-  libsparse   
        |-  libsuspend  
        |-  libsync 
        |-  libsysutils 
        |-  libusbhost  
        |-  libutils    
        |-  libziparchive   
        |-  lmkd    
        |-  logcat  
        |-  logd    
        |-  logwrapper  
        |-  mkbootimg   
        |-  reboot  
        |-  rootdir 
        |-  run-as  
        |-  sdcard  
        |-  toolbox 
        |-  trusty  
        |-  tzdatacheck 
    |-  extras // 核心库之外的程序,包括以下几个目录。        
        |-  alloc-stress    
        |-  ANRdaemon   
        |-  boot_control_copy   
        |-  bootctl 
        |-  brillo_config   
        |-  cppreopts   
        |-  cpustats    
        |-  crypto-perf 
        |-  ext4_utils  
        |-  f2fs_utils  
        |-  iotop   
        |-  kexec_tools 
        |-  ksmutils    
        |-  latencytop  
        |-  libfec  
        |-  libpagemap  
        |-  librank 
        |-  memcpy-perf 
        |-  memory_replay   
        |-  memtrack    
        |-  micro_bench 
        |-  mmap-perf   
        |-  multinetwork    
        |-  pagecache   
        |-  perfprofd   
        |-  postinst    
        |-  preopt2cachename    
        |-  procmem 
        |-  procrank    
        |-  puncture_fs 
        |-  runconuid   
        |-  sane_schedstat  
        |-  showmap 
        |-  showslab    
        |-  simpleperf  
        |-  slideshow   
        |-  sound   
        |-  squashfs_utils  
        |-  su  
        |-  systrace_analysis   
        |-  taskstats   
        |-  tests   
        |-  tools   
        |-  verity  
        |-  zram-perf   
    |-  gatekeeper // 防护程序,如锁屏密码等。      
    |-  hwservicemanager // Hardware Service Manager。       
    |-  keymaster // HAL密钥管理。       
    |-  libfmq // Message Queue。        
    |-  libhidl // Hardware Interface Description Language。     
    |-  libhwbinder // Hardware Binder。     
    |-  libufdt // Unflattened Device Tree。     
    |-  libvintf // Vendor Interface。       
    |-  media // 包括alsa、audio、brillo、camera和radio。      
    |-  nativepower // 用于Brillo的电源管理模块,包括客户端的libnativepower和服务端的nativepowerman以及示例代码。       
    |-  netd // 网络模块,包括client和server。       
    |-  nfc // Near Field Communication。        
    |-  nvram // NVRAM访问控制。     
    |-  security // 安全模块,包括keystore和软件模拟的softkeymaster。     
    |-  sepolicy // Android SELinux policy configuration。       
    |-  tools // 包括aidi和hidl。       
    |-  tpm // Trusted Platform Module,一种安全防御工具。        
    |-  update_engine // 系统升级。      
    |-  vold // Volume服务,如sdk卡、usb等。        
|-  test // Android Vendor测试框架,包括以下几个目录。            
    |-  vts // Vendor Test Suite。       
    |-  vts-testcase // VTS测试用例,包括fuzz、kernel、performance和security。     
|-  toolchain // Android工具链,包括一个binutils目录。         
    |-  binutils // bin utilities。      
|-  tools // Android工具集,包括以下几个目录。           
    |-  apksig // APK签名,包括一个Java库和一个Java命令行工具。      
    |-  external // 外部工具,包括以下几个目录。      
        |-  fat32lib // 用于FAT文件系统。  
        |-  gradle // Gradle各种版本的源码压缩包。 
    |-  loganalysis // log分析的Java类库。        
    |-  repohooks // 用于repo upload,报告各仓库的修改情况。      
    |-  test // 测试框架,Python实现。      
    |-  tradefederation // 服务于测试。       
作者:iEearth 发表于2017/3/22 20:40:20 原文链接
阅读:192 评论:0 查看评论
Viewing all 35570 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>