集合类型

集合类型

 

前面几章里,我们学习了四种基本数据类型,两种简单的自定义类型。这一章,我们学习一种自定义结构类型:集合类型。集合在数学中较常见,是若干个同类型数据的全部。在TURBO  PASCAL中,集合的意义和数学中比较类似,但是为了编译的效率起见,TURBO  PASCAL限制了集合的数量不能无限制的大,必须有一个范围。

 

 一、集合的定义

    在PASCAL中,我们把有限个同类数据的全体称为集合。为了体现它的全体性,我们用中括号把属于一个集合的数括起来。如:[1,2,3,4,9,-3,11],[‘A’,‘B’,‘C’,‘D’]。对于集合中的这些数据,规定必须是有序的。

集合定义的格式如下:

TYPE  集合类型名=SET  OF  基本数据类型;

在这里,基本数据类型是指:字符型,整型中的子界型,布尔型,枚举型,子界型。整型和实型是不允许的,因为它们是无限集合。

1:

TYPE

  NUMBER=SET  OF  1..100;

 CH1=SET  OF  ‘A’..‘Z’;

  CH2=SET  OF  CHAR;

COLOR=(RED,ORANGE,YELLOW,GREEN,INDIGO,BLUE,VIOLET);

CO1=SET  OF  COLOR;

 

以上定义了NUMBER,CH1,CH2,CO1四个集合。在定义CO1之前,先定义了枚举型COLOR。

  VAR 

A,   B:NUMBER;

C:CH1;

D:CH2;

E,F:CO1;

这样,定义了6个集合变量A,B,C,D,E,F。下面可以对它们赋值:

    A:=[34,17,22,8,66,22];

    B:=[10,1,8,59];

    C:=[‘H’,‘Q’,‘G’,‘U’,‘A’];   

    E:=[YELLOW,GREEN,VIOLET,BLUE]

    F:=[]

集合变量的取值一定要和集合变量的类型一至。集合中的数据有以下特征:

1    集合中的数的个数是没有明确的限定,如有多个,则各个数据之间用逗号隔开。

2    集合中的数据允许重复出现,无论出现多少次,系统也只把它们当作一个数据看待。

3    集合中的数据是无序的,谁前谁后一个样。

4    集合中可以没有数据,我们称之为空集。

5    一个集合中的数据只能为同一种数据类型。

6    在集合中的数据如果是连续的有序型,则可以用子界型表示。如A:=[1..20]。

其实,在集合的定义部分,可以把集合类型定义和集合变量说明两步合并为一步进行:

VAR  集合变量名:SET  OF  基本数据类型;

那么,前面的定义可以表示为:

VAR 

A,B:SET  OF  1..100;

 C:SET  OF  ‘A’..‘Z’;

 D:SET  OF  CHAR;

CO1:SET  OF  (RED,ORANGE,YELLOW,GREEN,INDIGO,BLUE,VIOLET);

 

二、集合类型的运算

    2.1  赋值运算

赋值运算就是对已经定义好的集合变量进行赋值。如:

  A:=[1,3,5,99];

  B:=A;

C:=[];

其中,C是空集。

2.2  关系运算

在集合的关系运算里,有5种运算符:=,<>,>=,<=,IN。下面,我们来一一分析它们。

1)                        相等判断(=,<>=)

“=”表示两集合相等,“<>”表求两集合不等。这个运算符是判断两同数据类型的集合是否相等。相等的依据是:两集合A,B中,A中的全部数据在B中都有,B中的全部数据在A中都有。这里没要求数据的先后顺序,也没要求两集合中数的个数必须相等。

例2                     写出下面集合运算的结果。

[1,2,3,4]=[1,4,3,2,]        TRUE

[3,6,9,4,7]<>[3,6,9,4]     TRUE

[3,6,9,4,3]<>[6,9,4,3]     FALSE

[]=[]                              TRUE

2)                         包含运算(<=,>=)

在集合运算中,没有>,<,只有<=,>=。它们表示两个集合的包含关系。<=表示前者是后者的子集,>=表示后者是前者的子集。

例3              写出下列集合运算的结果。

    [1,2,3,4]<=[1,2,3,4,5]        TRUE             

    [1,2,3]<=[1,2,3]                 TRUE

[1,2,3]>=[1,2,3]                 TRUE

[1,2,3,4,5,6]>=[4,9]           FALSE

[]<=[1]                             TRUE

 我们说的子集关系是这样:如果A是B的子集,则A中所有数据在B中都能找到。空集是任何集合的子集。     

3)      IN  运算

上面的运算中进行运算的都是集合,而IN运算的意思是判断一个元素是否在一个集合内。作为一个元素,则在书写时不用加中括号了。

例4      写出下面运算的结果。

2  IN  [1,2,3]                    TRUE

A’  IN  [‘A’,‘C’,‘E’,‘G’]    TRUE

6  IN  []                           FALSE

3  IN  [4,6,9]                    FALSE

  2.3  逻辑运算。        

集合的逻辑运算和其它不一样:它运算出来不是布尔值,而是一个集合。集合的逻辑运算有三种:并(+),交(*),差(-)。

1        

两集合A,B相并指的是有A,B两集合,将其中一个集合去掉它们的公共元素后再把二集合中的元素合并在一个集合里。并的操作用“+”表示。

5  

 [1,2,3]+[2,3,4]=[1,2,3,4]

[1,5]+[2]=[1,2,5]

[1,4]+[1,4]=[1,4]

[5,6,7]+[]=[5,6,7]

2      

两集合A,B相交指的是有A,B两集合,把它们的公共值取出来生成一个新的集合。交的操作用“*”表示。例6

    [1,2,3]*[2,3,4]=[2,3]

[1,2,3]*[1,2,3]=[1,2,3]

[3,6,8]*[4,9]=[]

[1,2,3,4,5,6]*[3]=[3]

[RED,YELLOW,BIUE]*[YELLOE,VIOLET]=[YELLOW]

3        

差的操作用“-”表示。两集合A,B的差指的是假设有A,B两集合,找出集合A,B中的公共元素,在集合A中减去公共元素后的结果便是A-B的差。

7

[1,2,3,4]-[2,3,4]=[1]

[1,2,3,4]-[4,5,6,7]=[1,2,3]

[1,2,3,4]-[5,6,7,8]=[1,2,3,4]

[4,5,6]-[4,5,6]=[]

[4,7,9]-[]=[4,7,9]

当在一个表达式中,同时出现了+,-,*三种运算符时,其运算的先后顺序是先*,后+,-。+,-符号同级别,运算时依从左到右的顺序执行。  

 

三、集合的应用    

1  集合运算.建立两个集合,然后对它们进行各种集合运算并输出运算结果。设该全集为[a,b,c,d,e,f],x=[a,b,c],y=[b,c,d],计算x+y,x*y,x-y,判断x是否包含y,d是否属于集合x-y。

算法分析:

1、          集合的建立:集合的建立可以通过赋值语句直接实现,也可以先初始化一个集合,然后利用集合的并运算逐一加入元素,形成所需集合。

2、          集合的运算:逻辑运算,关系运算。注意类型匹配。

3、          集合的输出:集合的输出必须通过测试输出,利用in 运算完成。

 

 

源程序如下:

      Program jhys;

        Type

           letter=(a,b,c,d,e,f);

           set1=set  of  letter;

         Var

            x,y,z1,z2,z3:set1;

            c1,c2:Boolean;

            i:letter;

          Procedure  setout(z:set1);

             Var

                ch:char;

                k:letter;

              Begin

                write(‘[‘);

                For k:=a to f do

                  If k  in  z  then  begin

                                       Ch:=chr(ord(k)+ord(‘a’));

                                       Write(ch:2);

                                     End;

                   Writeln(‘]’);

                End;

            Begin

               x:=[a,b,c];

               y:=[];

               for i:=b to  d  do  y:=y+[i];

               z1:=x+y;

               z2:=x*y;

               z3:=x-y;

               c1:=x>=y;

               c2:=d  in z3;

               Write(‘x=’);setout(x);

               Write(‘y=’);setout(y);

               Write(‘z1=’);setout(z1);

               Write(‘z2=’);setout(z2);

               Write(‘z3=’);setout(z3);

               Writeln(‘x>=y is’,c1);

               Writeln(‘d  in  x-y  is’,c2);

               Readln;

            End.

   

2  读入一串字符,以?结束。该字符串是数字和字母的组合。求字母和数字的个数。

分析:我们先设好两个集合,一个是‘0’-‘9’的数字集合,一个是‘A’到‘Z’的字母集合。每输入一个字符便判一次是属于哪个集合,然后得出结果。

            PROGRAM e8(input,output);

              VAR number:set of '0'..'9';

                  ch1:set of 'a'..'z';

                  ch2:set of 'A'..'Z';

                  n,c:integer;

                  ch:char;

               BEGIN

                ch1:=['a'..'z'];

                ch2:=['A'..'Z'];

                number:=['0'..'9'];

                n:=0;

                c:=0;

                read(ch);

                while ch<>'?' do

                 begin

                 if (ch in ch1) or (ch in ch2) then c:=c+1;

                 if ch in number then n:=n+1;

                 read(ch);

                 end;

                writeln('number=',n,'  ','char=',c);

                END.

例3   将一16位的二进制数变成十进制数。

二进制变成十进制数的方法我们早已熟悉。我们编写一个函数专门求2的N次方,最后将它们相加。        

 PROGRAM e9(input,output);

                    FUNCTION CF(n:integer):longint;

                      var i:integer;

                          s:longint;

                      begin

                        s:=1;

                        if n=0 then cf:=1 else

                        begin

                        for  i:=1 to n do

                         s:=s*2;

                         cf:=s;

                        end;

                       end;

                     VAR b:set of 0..15;

                         a,j:integer;

                         c:longint;

                    BEGIN

                         b:=[];

                         c:=0;

                         writeln('input a 16_bit number');

                         for j:=15 downto 0 do

                          begin

                              read(a);

                              if a=1 then b:=b+[j];

                           end;

                          for j:=0 to 15 do

                            if j in b then  c:=c+cf(j);

                          writeln('c=',c);

                      END.

      在这个程序中,在输入16位二进制数时,每输一个数要敲一个空格键。

4  将十进制整数k转换位二进制数,以集合类型变量buf表示一个16位二进制数,如18的二进制数位10010。则buf中记为[2,5]。即表示右起第2位,第5位是1,其余位为0。最后输出10010。

   program  ex4;

     var

       buf:set  of  0..15;

       i,k:integer;

      begin

        write(‘k=’);

        readln(k);

        buf:=[];

        i:=0;

        while  (k<>0)and(k<>1) do  begin

                                      if odd(k) then  buf:=buf+[i];

                                      inc(i);

                                      k:=k  div  2;

                                    end;

        if k=1 then  buf:=buf+[i];

        k:=0;

        for i:=15  downto  0  do

             if i  in  buf  then  begin 

                                     k:=i;

                                     break;

                                   end;

         for  i:=k downto  0  do

              if i  in  buf  then write(‘1’)

              else  write(‘0’);

          readln;

       end.

5 筛选法求素数。

算法分析:我们先看一个例子,通过此例子分析一下筛选法求素数的过程:

n=20,即求2到20 之间的素数。

(1)       先把2到20 之间所有的数全部放入一个筛子中(即集合中);

(2)       在筛子中选择最小的元素i,把此数添加到集合p中p:=p+[i];

(3)       将素数i的所有倍数在集合中晒去。

for j:=1 to  (n div i)  do   s:=s-[j*i];

(4)       如果筛子不空,则重复(2)、(3)步。我们将每一次的筛子集合s和素数集合p列出:

  

筛子集合s

素数集合p

 

[2..20]

[]

 

[3,5,7,9.11,13,15,17,19]

[2]

i:=2

[5,7,11,13,17,19]         

[2,3]

i:=3

[7,11,13,17,19]

[2,3,5]

i:=5

[11,13,17,19]

[2,3,5,7]

i:=7

[13,17,19]

[2,3,5,7,11]

i:=11

[17,19]

[2,3,5,7,11,13]

i:=13

[19]

[2,3,5,7,11,13,17]

i:=17

[]

[2,3,5,7,11,13,17,19]

i:=19

  program  primenumber;

const

   N=200;

type

   tgather=set  of  2..N;

var

   primes,sieve:tgather;  {素数集合筛子}

   total,i,j:integer;   {计数器,素数,循环变量}

begin 

  sieve:=[2..N];          {将全部数放入筛子中}

  primes:=[];

  i:=2;

  repeat  {挑选筛中存在的最小数i(此数即为素数)}

     while  not (i in  sieve) do  inc(i);

    {将素数i加入到素数集合primes}

     primes:=primes+[i];

    {在筛子sieve筛去素数i的倍数}

 for j:=1 to  (N div i)  do   sieve:=sieve-[j*i];

   until sieve=[];  {直至筛子中为空}

   {输出素数集合primes}

   total:=0;

   for i:=2 to  N do

      if  i  in  primes  then  begin

                                  inc(total);

                                  write(i:4);

                                  if total mod 10=0 then  writeln;

                               end;

   writeln(‘count=’,total); readln;

end.

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值