The Fourth Dimension Space

枯叶北风寒,忽然年以残,念往昔,语默心酸。二十光阴无一物,韶光贱,寐难安; 不畏形影单,道途阻且慢,哪曲折,如渡飞湍。斩浪劈波酬壮志,同把酒,共言欢! -如梦令

#

ACM中java的使用

 

这里指的java速成,只限于java语法,包括输入输出,运算处理,字符串和高精度的处理,进制之间的转换等,能解决OJ上的一些高精度题目。

1. 输入:
格式为:Scanner cin = new Scanner (new BufferedInputStream(System.in));

例程:
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;

public class Main
{
    public static void main(String[] args)
    {
        Scanner cin = new Scanner (new BufferedInputStream(System.in));
        int a; double b; BigInteger c; String st;
        a = cin.nextInt(); b = cin.nextDouble(); c = cin.nextBigInteger(); d = cin.nextLine(); // 每种类型都有相应的输入函数.
    }
}


2. 输出
函数:System.out.print(); System.out.println(); System.out.printf();
System.out.print(); // cout << …;
System.out.println(); // cout << … << endl;
System.out.printf(); // 与C中的printf用法类似.

例程:
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;

public class Main
{
    public static void main(String[] args)
    {
        Scanner cin = new Scanner (new BufferedInputStream(System.in));
        int a; double b;
        a = 12345; b = 1.234567;
        System.out.println(a + " " + b);
        System.out.printf("%d %10.5f\n", a, b); // 输入b为字宽为10,右对齐,保留小数点后5位,四舍五入.
    }
}

规格化的输出:
函数:
// 这里0指一位数字,#指除0以外的数字(如果是0,则不显示),四舍五入.
    DecimalFormat fd = new DecimalFormat("#.00#");
    DecimalFormat gd = new DecimalFormat("0.000");
    System.out.println("x =" + fd.format(x));
    System.out.println("x =" + gd.format(x));


3. 字符串处理
java中字符串String是不可以修改的,要修改只能转换为字符数组.

例程:
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;

public class Main
{
    public static void main(String[] args)
    {
        int i;
        Scanner cin = new Scanner (new BufferedInputStream(System.in));
        String st = "abcdefg";
        System.out.println(st.charAt(0)); // st.charAt(i)就相当于st[i].
        char [] ch;
        ch = st.toCharArray(); // 字符串转换为字符数组.
        for (i = 0; i < ch.length; i++) ch[i] += 1;
        System.out.println(ch); // 输入为“bcdefgh”.
if (st.startsWith("a")) // 如果字符串以'0'开头.
        {
            st = st.substring(1); // 则从第1位开始copy(开头为第0位).
        }
    }
}


4. 高精度
BigInteger和BigDecimal可以说是acmer选择java的首要原因。
函数:add, subtract, divide, mod, compareTo等,其中加减乘除模都要求是BigInteger(BigDecimal)和BigInteger(BigDecimal)之间的运算,所以需要把int(double)类型转换为BigInteger(BigDecimal),用函数BigInteger.valueOf().

例程:
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;

public class Main
{
    public static void main(String[] args)
    {
        Scanner cin = new Scanner (new BufferedInputStream(System.in));
        int a = 123, b = 456, c = 7890;
        BigInteger x, y, z, ans;
        x = BigInteger.valueOf(a); y = BigInteger.valueOf(b); z = BigInteger.valueOf(c);
        ans = x.add(y); System.out.println(ans);
        ans = z.divide(y); System.out.println(ans);
        ans = x.mod(z); System.out.println(ans);
        if (ans.compareTo(x) == 0) System.out.println("1");
    }
}


5. 进制转换
java很强大的一个功能。
函数:
String st = Integer.toString(num, base); // 把num当做10进制的数转成base进制的st(base <= 35).
int num = Integer.parseInt(st, base); // 把st当做base进制,转成10进制的int(parseInt有两个参数,第一个为要转的字符串,第二个为说明是什么进制).  
BigInter m = new BigInteger(st, base); // st是字符串,base是st的进制.

//Added by abilitytao
1.如果要将一个大数以2进制形式读入 可以使用cin.nextBigInteger(2);
当然也可以使用其他进制方式读入;
2.如果要将一个大数转换成其他进制形式的字符串 使用cin.toString(2);//将它转换成2进制表示的字符串
例程:POJ 2305

import java.io.*;
import java.util.*;
import java.math.*;

public class Main
{
    
public static void main(String[] args)
    
{
        
int b;
        BigInteger p,m,ans;
        String str ;
        Scanner cin 
= new Scanner (new BufferedInputStream(System.in));
        
while(cin.hasNext())
        
{
            b
=cin.nextInt();
            
if(b==0)
                
break;
            p
=cin.nextBigInteger(b);
            m
=cin.nextBigInteger(b);
            ans
=p.mod(m);
            str
=ans.toString(b);
            System.out.println(str);
        }

    }

}

//End by abilitytao


6. 排序
函数:Arrays.sort();至于怎么排序结构体,像C++里写个cmp的方法,在java还不太清楚,希望有人指点下~~

例程:
import java.io.*;
import java.math.*;
import java.util.*;
import java.text.*;

public class Main
{
    public static void main(String[] args)
    {
        Scanner cin = new Scanner (new BufferedInputStream(System.in));
        int n = cin.nextInt();
        int a[] = new int [n];
        for (int i = 0; i < n; i++) a[i] = cin.nextInt();
        Arrays.sort(a);
        for (int i = 0; i < n; i++) System.out.print(a[i] + " ");
    }
}


7. POJ高精度题目汇总:
POJ 1131 1205 1220 1405 1503 1604 1894 2084 2305 2325 2389 2413 3101 3199


转自:http://hi.baidu.com/czyuan_acm/blog/item/d0bf7a439d90d21b72f05d69.html


acm中Java的应用

Chapter I.

Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点:

(1) 最明显的好处是,学会Java,可以参加Java Challenge    :)
(2) 对于熟悉C/C++的程序员来说,Java 并不难学,找本书,一两周业余时间就可以搞定了。当然,这里只是指一般编程,想熟悉所有的Java库还是需要些时间的。
      事实上,Java 只相当于C++的一个改进版,所有的语法都几乎是C++的,很少有变动。
(3) 在一般比赛中,Java程序会有额外的时间和空间,而实际上经过实验,在执行计算密集任务的时候Java并不比C/C++慢多少,只是IO操作较慢而已。
(4) Java 简单而功能强大,有些东西用Java实现起来更为方便,比如高精度。
(5) 用Java不易犯细微的错误,比如C/C++中的指针, “if (n = m) ... ” 等
(6) 目前来看Eclipse已成基本配置,写Java程序反而比C/C++更方便调试。在具体竞赛时也算多一种选择。
(7) 学会Java对以后工作有好处。现在国外很多地方会Java的人比会C/C++的人多。
(8) 会Java可以使你看起来更像偶蹄类动物(牛)      hoho~


Chapter II.

下面说一下ACM-ICPC队员初用Java编程所遇到的一些问题:

1. 基本输入输出:

(1)
JDK 1.5.0 新增的Scanner类为输入提供了良好的基础,简直就是为ACM-ICPC而设的。

一般用法为:

import java.io.*
import java.util.*

public class Main
{
      public static void main(String args[])
      {
          Scanner cin = new Scanner(new BufferedInputStream(System.in));
          ...
      }
}

当然也可以直接 Scanner cin = new Scanner(System.in);
只是加Buffer可能会快一些

(2)
读一个整数:    int n = cin.nextInt();          相当于    scanf("%d", &n);    或 cin >> n;
读一个字符串:String s = cin.next();          相当于    scanf("%s", s);      或 cin >> s;
读一个浮点数:double t = cin.nextDouble();    相当于    scanf("%lf", &t); 或 cin >> t;
读一整行:      String s = cin.nextLine();      相当于    gets(s);            或 cin.getline(...);
判断是否有下一个输入可以用 cin.hasNext() 或 cin.hasNextInt() 或 cin.hasNextDouble() 等,具体见 TOJ 1001 例程。

(3)
输出一般可以直接用 System.out.print() 和 System.out.println(),前者不输出换行,而后者输出。
比如:System.out.println(n);    // n 为 int 型
同一行输出多个整数可以用
      System.out.println(new Integer(n).toString() + " " + new Integer(m).toString());

也可重新定义:

static PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
cout.println(n);

(4)
对于输出浮点数保留几位小数的问题,可以使用DecimalFormat类,

import java.text.*;
DecimalFormat f = new DecimalFormat("#.00#");
DecimalFormat g = new DecimalFormat("0.000");
double a = 123.45678, b = 0.12;
System.out.println(f.format(a));
System.out.println(f.format(b));
System.out.println(g.format(b));

这里0指一位数字,#指除0以外的数字。


2. 大数字

BigInteger 和 BigDecimal 是在java.math包中已有的类,前者表示整数,后者表示浮点数

用法:
不能直接用符号如+、-来使用大数字,例如:

(import java.math.*)    // 需要引入 java.math 包

BigInteger a = BigInteger.valueOf(100);
BigInteger b = BigInteger.valueOf(50);
BigInteger c = a.add(b)    // c = a + b;

主要有以下方法可以使用:
BigInteger add(BigInteger other)
BigInteger subtract(BigInteger other)
BigInteger multiply(BigInteger other)
BigInteger divide(BigInteger other)
BigInteger mod(BigInteger other)
int compareTo(BigInteger other)
static BigInteger valueOf(long x)

输出大数字时直接使用 System.out.println(a) 即可。


3. 字符串

String 类用来存储字符串,可以用charAt方法来取出其中某一字节,计数从0开始:

String a = "Hello";      // a.charAt(1) = ’e’

用substring方法可得到子串,如上例

System.out.println(a.substring(0, 4))      // output "Hell"

注意第2个参数位置上的字符不包括进来。这样做使得 s.substring(a, b) 总是有 b-a个字符。

字符串连接可以直接用 + 号,如

String a = "Hello";
String b = "world";
System.out.println(a + ", " + b + "!");      // output "Hello, world!"

如想直接将字符串中的某字节改变,可以使用另外的StringBuffer类。


4. 调用递归(或其他动态方法)

在主类中 main 方法必须是 public static void 的,在 main 中调用非static类时会有警告信息,
可以先建立对象,然后通过对象调用方法:

public class Main
{
      ...

      void dfs(int a)
      {
          if (...) return;
          ...
          dfs(a+1);
      }
     
      public static void main(String args[])
      {
          ...
          Main e = new Main();
          e.dfs(0);
          ...
      }
}

5. 其他注意的事项

(1) Java 是面向对象的语言,思考方法需要变换一下,里面的函数统称为方法,不要搞错。

(2) Java 里的数组有些变动,多维数组的内部其实都是指针,所以Java不支持fill多维数组。
      数组定义后必须初始化,如 int[] a = new int[100];

(3) 布尔类型为 boolean,只有true和false二值,在 if (...) / while (...) 等语句的条件中必须为boolean类型。
      在C/C++中的 if (n % 2) ... 在Java中无法编译通过。

(4) 下面在java.util包里Arrays类的几个方法可替代C/C++里的memset、qsort/sort 和 bsearch:

Arrays.fill()
Arrays.sort()
Arrays.binarySearch()  

转自:http://hi.baidu.com/oak_wesley/blog/item/35839200fd9dc10e1d9583de.html


Java进制转换~集锦

由于Unicode兼容ASCII(0~255),因此,上面得到的Unicode就是ASCII。

java中进行二进制,八进制,十六进制,十进制间进行相互转换      
Integer.toHexString(int i)
十进制转成十六进制
Integer.toOctalString(int i)
十进制转成八进制
Integer.toBinaryString(int i)
十进制转成二进制
Integer.valueOf("FFFF",16).toString()
十六进制转成十进制
Integer.valueOf("876",8).toString()
八进制转成十进制
Integer.valueOf("0101",2).toString()
二进制转十进制

至于转换成二进制或其他进制,Java API提供了方便函数,你可以查Java的API手册。
以字符a的ASCII为例:
int i = 'a';
String iBin = Integer.toBinaryString(i);//二进制
String iHex = Integer.toHexString(i);//十六进制
String iOct = Integer.toOctalString(i);//八进制
String iWoKao = Integer.toString(i,3);//三进制或任何你想要的35进制以下的进制
DEC

有什么方法可以直接将2,8,16进制直接转换为10进制的吗?
java.lang.Integer类
parseInt(String s, int radix)
使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
examples from jdk:
parseInt("0", 10) returns 0
parseInt("473", 10) returns 473
parseInt("-0", 10) returns 0
parseInt("-FF", 16) returns -255
parseInt("1100110", 2) returns 102
parseInt("2147483647", 10) returns 2147483647
parseInt("-2147483648", 10) returns -2147483648
parseInt("2147483648", 10) throws a NumberFormatException
parseInt("99", 8) throws a NumberFormatException
parseInt("Kona", 10) throws a NumberFormatException
parseInt("Kona", 27) returns 411787

进制转换如何写(二,八,十六)不用算法
Integer.toBinaryString
Integer.toOctalString
Integer.toHexString

例一:

public class Test{
public static void main(String args[]){

   int i=100;
   String binStr=Integer.toBinaryString(i);
   String otcStr=Integer.toOctalString(i);
   String hexStr=Integer.toHexString(i);
   System.out.println(binStr);

例二:

public class TestStringFormat {
public static void main(String[] args) {
   if (args.length == 0) {
      System.out.println("usage: java TestStringFormat <a number>");
      System.exit(0);
   }

   Integer factor = Integer.valueOf(args[0]);

   String s;

   s = String.format("%d", factor);
   System.out.println(s);
   s = String.format("%x", factor);
   System.out.println(s);
   s = String.format("%o", factor);
   System.out.println(s);
}
}


各种数字类型转换成字符串型:

String s = String.valueOf( value); // 其中 value 为任意一种数字类型。

字符串型转换成各种数字类型:

String s = "169";
byte b = Byte.parseByte( s );
short t = Short.parseShort( s );
int i = Integer.parseInt( s );
long l = Long.parseLong( s );
Float f = Float.parseFloat( s );
Double d = Double.parseDouble( s );

数字类型与数字类对象之间的转换:

byte b = 169;
Byte bo = new Byte( b );
b = bo.byteValue();

short t = 169;
Short to = new Short( t );
t = to.shortValue();

int i = 169;
b = bo.byteValue();

short t = 169;
Short to = new Short( t );
t = to.shortValue();

int i = 169;
Integer io = new Integer( i );
i = io.intValue();

long l = 169;
Long lo = new Long( l );
l = lo.longValue();

float f = 169f;
Float fo = new Float( f );
f = fo.floatValue();

double d = 169f;
Double dObj = new Double( d );
d = dObj.doubleValue();

posted @ 2009-10-16 19:13 abilitytao 阅读(1210) | 评论 (4)编辑 收藏

[ACM必学]文件输入输出技巧(freopen函数) (转)

昨天发了一篇《C语言 使用文件输入/输出数据》,使用的是最普通的文件输入/输出方法,Felix大牛随后给了一种更简单的改进方法,在ACM中应用很广,而且超赞,现在来介绍一下。

这次用到的文件打开函数不再是fopen,而是stdio.h中包含的另一个函数freopen

FILE * freopen ( const char * filename, const char * mode, FILE * stream );

【参数说明】

filename: 要打开的文件名

mode: 文件打开的模式,和fopen中的模式(r/w)相同

stream: 文件指针,通常使用标准流文件(stdin/stdout/stderr)

【使用方法】

因为文件指针使用的是标准流文件,因此我们可以不定义文件指针。

接下来我们使用freopen()函数以只读方式r(read)打开输入文件slyar.in

freopen("slyar.in", "r", stdin);

然后使用freopen()函数以写入方式w(write)打开输出文件slyar.out

freopen("slyar.out", "w", stdout);

接下来的事情就是使用freopen()函数的优点了,我们不再需要修改scanf和printf,而是维持代码的原样就可以了。因为freopen()函数重定向了标准流,使其指向前面指定的文件,省时省力啊,赞...

最后只要使用fclose关闭输入文件和输出文件即可。

fclose(stdin);
fclose(stdout);

若要恢复句柄,可以重新打开标准控制台设备文件,只是这个设备文件的名字是与操作系统相关的。

DOS/Win:

freopen("CON", "r", stdin);

Linux:

freopen("/dev/console", "r", stdin);

也附加一个代码模版:

#include <stdio.h>
             
int main()
{
     freopen(
"slyar.in""r", stdin);
     freopen(
"slyar.out""w", stdout);
             
     
/* 中间按原样写代码,什么都不用修改 */
             
     fclose(stdin);
     fclose(stdout);
     
return 0;
}

PS.刚才发现一个问题,就是在用C-free编译含有文件操作的源码时,必须要将fopen或者freopen放到所有变量定义的下面,否则会编译错误...囧

转自:http://www.slyar.com/blog/c-freopen-stdin-stdout.html

posted @ 2009-10-13 22:43 abilitytao 阅读(2212) | 评论 (3)编辑 收藏

Hello ,Java world

第一个 JAVA程序 ,纪念一下 ^_^

/**
 * @(#)Welcome.java
 * Coded by abilitytao 
 * 
@version 1.00 2009/9/30
 
*/


public class Welcome 
{
       
    
public static void main(String args[])
    
{
         String a
="Hello , JAVA World";
         System.out.println(a);
           
    }

}


posted @ 2009-09-30 13:30 abilitytao 阅读(232) | 评论 (0)编辑 收藏

POJ 2186 Popular Cows(图的连通性问题——有向图的强联通分量+缩点)

     摘要: 也许你能写出一段精致的文字,但你却未必能写出一段精辟的代码。这是我最近研究连通性问题的一个体验,有的人的书写了好几页纸,可是最终能用的却只有1,2句话而已,我觉得在计算机的世界,没有什么比代码更能直接地表达出这个算法的本质了!所以我以后要多读代码,少看那些空洞的文字。言归正传,来看题,这是我写的第一个强连通分量的题目,其实求强连通分量的步骤非常简单,正反两次使用dfs,就能得到联通分量的一切信息。...  阅读全文

posted @ 2009-09-26 17:40 abilitytao 阅读(2275) | 评论 (6)编辑 收藏

ZOJ 2588-Burning Bridges(图的连通性问题——求割边)

     摘要: 今天想看看关于桥的求法,搜到了这样一个题,由与网上缺少相关的资料,花了很多时间在找资料上,最后发现lrj的书上有这个问题的描述:无向图的割点和桥(见lrj书) 算法基于以下原理:(1)如果根顶点的儿子数大于1,则根顶点是割点(2)如果一个点和这个点的子孙都不存在指向这个点祖先的后向边,则这个点为割点。实现时需要对每个结点记录一个low值,表示该结点的子孙能够到达的最小的深度,如果这个值小于或等于该...  阅读全文

posted @ 2009-09-26 01:35 abilitytao 阅读(1485) | 评论 (0)编辑 收藏

位运算简介及实用技巧

     摘要: 位运算简介(By matrix67)  阅读全文

posted @ 2009-09-24 13:22 abilitytao 阅读(2042) | 评论 (2)编辑 收藏

内存池技术(转)

     摘要: 内存池技术 ACM的只要看前面的一部分就好了^_^  阅读全文

posted @ 2009-09-22 00:44 abilitytao 阅读(581) | 评论 (0)编辑 收藏

POJ 1330 Nearest Common Ancestors(tarjan LCA 算法)

     摘要:  关于LCA和RMQ问题 一、最近公共祖先(Least Common Ancestors) 对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。另一种理解方式是把T理解为一个无...  阅读全文

posted @ 2009-09-21 22:24 abilitytao 阅读(3519) | 评论 (1)编辑 收藏

9.20上海东华赛区网络赛H题 health (Dp+Dfs+Bit Operation)

Health

 

Unfortunately YY gets ill, but he does not want to go to hospital. His girlfriend LMY gives him N kinds of medicine, which may be helpful. It is not a good idea to take all of them, since taking several different kinds of medicine may cause undesirable side effects. Formally speaking, for each subset S of the N kinds of medicine (excluding the empty set), it has a health value v(S). If YY chooses to take a combination T of the medicines, the final effect to his illness is the sum of health values of all non-empty subsets of T.

YY wants to get healthy as quickly as possible, so the final effect of the medicines he takes should be as great as possible. Of course, YY may choose to take nothing, thus having a zero final effect, if he is too unlucky that all other alternatives he can get are negative…

 

Input

 Input contains multiple test cases.

For each test case, the first line contains a positive integer N (N16), the number of different kinds of medicine YY received from LMY.

The second line contains a single integer M (0M2N).

M lines follow, representing a list of health values.

Each of the M lines contains 2 integers, s (1s<2N) and v (-10000≤v≤10000), indicating a subset of the N kinds of medicine and its health value. Write s in binary representation and add leading zeros if needed to make it exactly N binary digits. If the ith binary digit of s is 1, then the subset it represents includes the ith kind of medicine; otherwise it does not.

It is guaranteed that no two lines of the list describe the same subset. All non-empty subsets that do not appear in the list have health value 0.

Input ends with N=0.

 

Output

 

For each test case, output one line with only one integer, the maximum final effect that can be achieved.

 

Sample Input

2

3

1 10

2 -1

3 100

0

 Sample Output

 109





比赛的时候,看到这道题过的人很多,但是自己却没什么思路,非常郁闷,一看题就知道肯定是个DP,可是究竟怎么动态规划呢?想了半天也想不出来,一直卡在这个题上,后来有个同学提示了我方法,这才明白过来,原来这里面还有位运算,看来我平时缺少位运算方面的训练了。。。哎 我还是太水。。。
分析:这个题的DP思想是把所有1 to 2^n-1的状态所对应的健康值都算出来,然后再其中取一个最大值。我们看看他是如何状态转移的:
            假设 n=3  现在考虑 1 1 1(7,从左到右分别是第3,2,1种药品) 这种状态,如果第三种药品不使用,那么相当于0 1 1 产生的 总健康值;
            这个健康值已经由它的子结构得到。
            如果使用第三种药品,那么我们进行一次DFS,将他对应的所有的有效状态(无效状态对应为0即可)对应的健康值加起来,这样就得到了
            使用第三种药物的总健康值。
            我们将上述子结构和DFS得到的结果相加,便得到了当前状态下的总健康值。
我们做一个循环,i from 1to 2^n-1 ,把所有情况对应的健康值算出来,然后再其中取一个最大值即可。(位运算很重要!)

#include<iostream>
using namespace std;
#define MAX (1<<17)

int value[MAX];
int dp[MAX];
int bin[20];
int n,m;
int sum;
int ans;

void dfs(int i,int p)
{

    
if(i<0)
    
{
        sum
+=value[p];
        
return ;
    }

    
else if(bin[i]==1)
        dfs(i
-1,p+(1<<i));
    dfs(i
-1,p);
}



void solve(int n)
{
    
int now=( (1<<n)-1 );
    
int i;
    
int j=1;
    
int k=-1;
    
for(i=1;i<=now;i++)
    
{
        sum
=0;
        memset(bin,
0,sizeof(bin));
        j
=1;
        k
=-1;
        
while(j*2<=i)
        
{

            
if(j&&i)
            
{
                k
++;
                bin[k]
=1;
            }

            
else 
            
{
                k
++;
                bin[k]
=0;
            }

            j
*=2;

        }

        dfs(k,j);
        dp[i]
=dp[i-j]+sum;
        
if(dp[i]>ans)
        ans
=dp[i];
    }



}



int main()
{
    
int i;
    
while(scanf("%d",&n))
    
{
        ans
=0;
        memset(value,
0,sizeof(value));
        
if(n==0)
            
break;
        scanf(
"%d",&m);
        
for(i=1;i<=m;i++)
        
{

            
int a,b;
            scanf(
"%d%d",&a,&b);
            value[a]
=b;
        }

        solve(n);
        printf(
"%d\n",ans);

    }

    
return 0;
}






做了这个题,突然想起了将10进制转化成2进制的方法,不断模除2,取余数,但是一直没有深究,今天终于明白了,原来如果把这个十进制数考虑成2进制,右移一位相当于除以2,模除2就是把最后那一位给取出来了,不断的模除2,就把这个2进制数一位一位的取出。
PS :感谢那位提示我思路的同学

posted @ 2009-09-21 14:28 abilitytao 阅读(1272) | 评论 (4)编辑 收藏

STL map常用操作简介(转)

1。目录

map简介
map的功能
使用map
在map中插入元素
查找并获取map中的元素
从map中删除元素
2。map简介

map是一类关联式容器 。它的特点是增加和删除节点对迭代器的影响很小 ,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。

3。map的功能

自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
快速插入Key - Value 记录。
快速删除记录
根据Key 修改value记录。
遍历所有记录。
4。使用map

使用map得包含map类所在的头文件
#include <map> //注意,STL头文件没有扩展名.h

map对象是模板类,需要关键字和存储对象两个模板参数:
std:map<int, string> personnel;
这样就定义了一个用int作为索引,并拥有相关联的指向string的指针.

为了使用方便,可以对模板类进行一下类型定义,

typedef map<int, CString> UDT_MAP_INT_CSTRING;
UDT_MAP_INT_CSTRING enumMap;

5。在map中插入元素

改变map中的条目非常简单,因为map类已经对[]操作符进行了重载

enumMap[1] = "One";
enumMap[2] = "Two";
.....

这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two" ; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:

enumMap.insert (map<int, CString> :: value_type(2, "Two"))

6。查找并获取map中的元素

下标操作符给出了获得一个值的最简单方法:

CString tmp = enumMap[2];

但是,只有当map中有这个键的实例时才对 ,否则会自动插入一个实例,值为初始化值 。

我们可以使用Find()和Count()方法来发现一个键是否存在。

查找map中是否包含某个关键字条目用find() 方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.

int nFindKey = 2;            //要查找的Key
//定义一个条目变量(实际是指针)
UDT_MAP_INT_CSTRING::iterator it= enumMap.find(nFindKey);
if(it == enumMap.end()) {
    //没找到
}
else {
    //找到
}

通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据

7。从map中删除元素

移除某个map中某个条目用erase()

该成员方法的定义如下

iterator erase(iterator it); //通过一个条目对象删除
iterator erase(iterator first, iterator last);        //删除一个范围
size_type erase(const Key& key); //通过关键字删除
clear() 就相当于 enumMap.erase(enumMap.begin(), enumMap.end());

 

转自:http://blog.csdn.net/logic_nut/archive/2009/08/30/4498990.aspx

posted @ 2009-09-17 18:23 abilitytao 阅读(360) | 评论 (0)编辑 收藏

仅列出标题
共42页: First 24 25 26 27 28 29 30 31 32 Last