帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

比如我在工程文件夹下放了一个svm-train.exe的文件

这个exe文件调用后有输出信息。我很想知道这个exe调用过程中到底发生了什么事情。

在java中这样写

Runtime run = Runtime.getRuntime();
Process child = null;
InputStream is = null;

File env = new File(System.getProperty(“user.dir”));
child = run.exec(cmd,null,env);

这个env是用于找到工程的当前目录,相当于进入Dos后先cd到目录,cmd就是你在dos窗口那里打的命令。

run.exec(cmd,null,env);这句就开始执行了。并创建一个Process给child

网上有很多代码有这句:

while(true)
{
if(child.waitFor() == 0)
{
break;
}

}

但是注意如果进入 if(child.waitFor() == 0)
那这个程序就会卡死在这里,直到exe进程结束。这样如果你的exe会运行很长时间,那么在这段时间内就不能打印任何输出信息。

全代码如下:

  1. private static boolean CallSVM(String cmd)
  2. {
  3. Runtime run = Runtime.getRuntime();
  4. Process child = null ;
  5. InputStream is = null ;
    1. try
  6. {
  7. File env = new File(System.getProperty( “user.dir” ));
    1. child = run.exec(cmd, null ,env);
    1. String out = null ;
      1. // nomal process
  8. is = child.getInputStream();
  9. FileWriter fw = new FileWriter(env.getAbsolutePath()+ “//log.txt” );
  10. BufferedReader br = new BufferedReader( new InputStreamReader(is));
      1. while ((out = br.readLine())!= null )
  11. {
  12. fw.write(out+ “/r/n” );
  13. System.out.println(out);
  14. }
  15. while ( true )
  16. {
  17. if (child.waitFor() == 0 )
  18. {
  19. break ;
  20. }
    1. }
      1. fw.write( “-----------------/r/n” );
      1. fw.close();
  21. br.close();
    1. }
  22. catch (IOException ioe)
  23. {
  24. System.err.println( “cmd error:” +cmd);
  25. System.err.println(ioe.getMessage());
  26. return false ;
  27. } catch (InterruptedException e) {
  28. // TODO Auto-generated catch block
  29. if (child != null )
  30. child.destroy();
  31. e.printStackTrace();
  32. }
  33. return true ;
  34. }

这里一定要输出放前,waitFor放后

while((out = br.readLine())!=null)
{
fw.write(out+“/r/n”);
System.out.println(out);
}

while(true)
{
if(child.waitFor() == 0)
{
break;
}

}

另外程序在执行过程中while((out =
br.readLine())!=null)这里也会卡住,所以不用担心,调用的dos程序还没有输出,就已经执行到waitFor()那里去了。

这里犯得错误是使用c++的预编译头去编译c语言。

如果解决C1853这个错误呢?

其实就是对每一个.c文件加上

#include “stdafx.h”

然后把.c文件改为.cpp文件

然后在把工程属性中的

configuration properties中的c/c++中的Precompiled Header中的Create / use Precompile
Header 中的User precompile Header 改为

Create precompile Header

How to compile C programs with Microsoft Visual C++ 2005

By default, new _ applications _
created in
Microsoft Visual C++ 2005 Express edition create _ C++ _
_ source code _
.

Here is how to compile _ C _
code. Launch ** Visual C++
2005 Express Edition ** and create a new project. Choose _ Win 32 _
and Win
32 _ Console _
Application. Enter a name in the ** Name ** box below.

Now press the ** Next ** button and then the ** Finish ** button. This will
generate a file called _ name _ .cpp where _ name _ is your entered project
name. Now look to the Solution Explorer (if you can’t see it, click View on
the menu then Solution Explorer), click _ name _ .cpp and press F2. Now press
** backspace ** twice so you end up with _ name _ .c.

Press ** F7 ** To _ compile _
. If you get an error
that say “fatal error C1853: ‘Debug/name.pch’ precompiled header file is from
a previous version of the compiler, or the precompiled header is C++ and you
are using it from C (or vice versa)” then just click the project menu,
properties and change ** Create/Use Precompiled Header ** from _ Use
Precompiled Header _ to _ Create Precompoiled Header _ . Press the ** Apply **
button. It should now compile successfully when you press ** F7 ** .

Using Existing Code

Create an empty project as above and remove all lines except

#include “stdafx.h”

Then paste in your existing code after this include and save it. You should
now be able to compile (press ** F7 ** ) and run your application.

微软的研究方向:

多媒体,自然人机交互,Data-intensive computing(包括数据挖掘,检索等) ,search and online AD(广告),
Compute Science 基础

然后展示了几个很有趣的Demo:

Deblurred image(处理模糊数码照片)

Remote
Computer(这个项目的名字记不得了,不过是在局域网内2M带宽情况下,可以使用web浏览器remote几台机器的试验,据演示效果说:比过去remote
desktop 要好很多。)

Gigapixel image(这个图片像素很高,可以任意缩放,然后主要工作就是在拉近一个图片位置,例如拉近餐馆,就能听到关于餐馆的广告,其他的地方还有很多
声音和人为标注。)不过这个项目个人认为是AD方面的事情,背后需要大量的人力物力。不过是一个很好的AD创新。

为啥要research呢?1.为新产品,2为解决问,3早期系统预警。(Demo原型)

21的计算可能要服务的方面:health,Environment,Education, compute technology integrate .

搜索个性化,自然语言理解和识别,这里演示一个Automatic receptionist

云计算会带来很多问题:资源管理,访问权限,调度协作等。

Semantic and future of search

Search past        current            future

Directories          keyword       sematics

New                  Experienced    Sophisticated

content ---- user ---- action   -------->        sematics—>people—>intent

微软收购了一个PowerSet这个网站使用语义搜索的。

也就是使用多句话代替一句话。

The science of programming

computer software contains no more errors. programmer make no more mistakes.

programming is an Engineering discipline.

Semantics is the science of programming.

Software Engineering Toolset

computer science small ---->BIG

operating system run on the multicore

Horizon is "unlimited ", it is limited by our own imagination.

computer technology is used to computer technology.

what’s past is merely prologue.

认为发展的三个方向:

simulation

communication

_ Embodiment _

_ _

_ many problems: _

Deal with physical world , natural language is not avoided.

teach as wll as a person.

The machine can guass

明白Moore’s law, Aim for mass markets, learn how to deal with uncertainty, learn
how to advoid catastorphes.

这些获得图灵奖的家伙们,当时从来就未曾想过自己有获得图灵奖的那天。只是想知道问题的答案。不是辛勤于工作,也不是想做好什么事情,只是想做点有趣的事情。另外关键
是lucky。

Base rule do base.偶然听到这句话。莫非是越低级的规则改能做好底层工作吗?

计算新视野,21世纪的计算混了顿不错的午餐,发现北大的饭就是比中科院的饭菜好.这是为啥么。国家部门不发钱吗?
另外自己英语的确不怎么好,只有第一个上场的Butler LAMPSON和洪小文,沈向阳的讲话听懂了。其他听的云里雾里中。不过Tony
Hoare的慢速英语也听的差不多。另外,那个同声翻译真的是差…嗯嗯哦哦的讲话…所以索性关掉,听正版英语了。

午饭之时碰到了过去的学长,现在在做Web Search。聊了几句。往前走了几步发现了疯子,然后发现疯子对另外一个男的有莫大的兴趣,可惜那个男的只对另外两个女
的感兴趣。于是上前打声招呼,踹了疯子一脚,急急忙忙的回到讲堂。

按我的这篇文章所写:

http://blog.csdn.net/cctt_1/archive/2008/11/02/3206314.aspx

这里这里读出写入英文是没有问题的。

但是我们需要读出写入中文。我在mysql的表有一项设置字符集,改为了GBK编码。

但是还是使用了我上篇文章所写的编码,结果发现插入中文时变为:???

插入中英文结合时,全部的中文变为??英文不变。

在网上搜了下,然后将上篇文章的编码改为:

  1. private SqlAccess sqlAccess = new SqlAccess();
  2. private void button1_Click( object sender, EventArgs e)
  3. {
  4. DataSet ds = sqlAccess.SelectDataSet( “select * from users” );
    1. label1.Text = “” ;
  5. Array alist = ds.Tables[0].Rows[0].ItemArray;
  6. foreach ( object o in alist)
  7. {
  8. label1.Text += o.ToString();
  9. }
  10. UpdateName();
  11. }
  12. private const string sql = “UPDATE USERS SET userName=@userName  WHERE userID=@userID” ;
  13. private const string userName = “@userName” ;
  14. private const string userID = “@userID” ;
  15. private void UpdateName()
  16. {
  17. int i = 1;
  18. string name = GB2312_ISO8859( “和好多岁收到暗示” );
  19. MySqlParameter[] my =
  20. {
  21. new MySqlParameter(userName,MySqlDbType.String),
  22. new MySqlParameter(userID,MySqlDbType.Int32)
  23. };
  24. my[0].Value = name;
  25. my[1].Value = i;
  26. label2.Text = sqlAccess.EXESql(sql, my).ToString();
  27. }
    1. //写入数据库时要进行gb2312转换到iso8895
  28. public string GB2312_ISO8859( string srcString)
  29. {
  30. //字符集gb2312转为iso8859
  31. System.Text.Encoding iso8859=System.Text.Encoding.GetEncoding( “iso8859-1” );
  32. System.Text.Encoding gb2312=System.Text.Encoding.GetEncoding( “gb2312” );
  33. return iso8859.GetString(gb2312.GetBytes(srcString));
  34. }

发现还是原来的问题。然后又搜了搜mysql的中文文档。发现好像column还是有字符集属性的…怎么不知道为啥这样做…太麻烦了。于是改了每一个表中需要中
文的列都改为了gbk,在mysql图形界面的字段详细资料中。但是如果你是使用的mysql非图形界面…那就要辛苦的alter
吧.改完后,运行成功,再也没有??了。

发现windowsApplication使用的string是gb2312编码,但是显示的时候gb2312和iso8895-1都可以。

所以在写入数据库时要转换为iso8895-1编码。注意这里如果转为System.Text.Encoding.GetEncoding(“GBK”)是不可以的。

首先去mysql网站下载一个mysql非安装版本

_ http://dev.mysql.com/downloads/mysql/5.0.html _

如果你感觉使用dos命令行不方便的话,可以顺便也下载一个GUI客户端:

_ http://dev.mysql.com/downloads/gui-tools/5.0.html _

然后打开vs…这个版本必须是2003以上。

然后呢,建立一个windowsApplication工程,然后在里面的app.config

如果你想把连接字符串写在程序里的话:将下面的代码改为 ** string ** strConn =  “server=localhost;user
id=root;password=;database=test;allow zero datetime= ** true ** ;”

这里与sqlserver连接字符串相区别的是:

user->user id,

当然估计没有下载MySql.Data.dll所以在

_ http://dev.mysql.com/downloads/connector/net/5.2.html _
下载

然后在net工程里添加引用,找到刚才你下载MySql.Data.dll的压缩包,解压后,在bin目录下有MySql.Data.dll.

添加成功后,在你的代码里添加一个

using MySql.Data.MySqlClient;

然后下面的和SqlClient的效果是一样的。只不过前面多了"My"

下面看具体的代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data;
  5. using MySql.Data.MySqlClient;
      1. namespace SqlConnect
  6. {
  7. /// 
  8. /// author: chico chen
  9. /// date: 2008-11-02
  10. /// 
  11. public class SqlAccess
  12. {
  13. private MySqlConnection conn = null ;
  14. private MySqlCommand cmd = null ;
  15. /// 
  16. /// 建立与数据库的连接
  17. /// 
  18. /// 
  19. private MySqlConnection CreateConn()
  20. {
  21. string strConn = System.Configuration.ConfigurationSettings.AppSettings[ “Restaurant” ].ToString();
  22. // SqlConnection 对象
  23. conn = new MySqlConnection(strConn);
  24. try
  25. {
  26. conn.Open();
  27. return conn;
  28. }
  29. catch (Exception e)
  30. {
  31. Console.WriteLine( “sql 连接未打开” );
  32. return null ;
  33. }
  34. }
  35. /// 
  36. /// 关闭与数据库的连接
  37. /// 
  38. private void CloseConn()
  39. {
  40. try
  41. {
  42. conn.Close();
  43. }
  44. catch (Exception e)
  45. {
  46. Console.WriteLine( “sql 连接未关闭” );
  47. }
  48. }
    1. /// 
  49. /// 查询数据库
  50. /// 
  51. /// 类似于SELECT * FROM [User];
  52. /// 
  53. public DataSet SelectDataSet( string sql)
  54. {
  55. CreateConn();
  56. MySqlDataAdapter sda = new MySqlDataAdapter(sql, conn);
  57. DataSet ds = new DataSet();
  58. sda.Fill(ds);
  59. CloseConn();
  60. return ds;
  61. }
  62. /// 
  63. /// 执行无返回值的sql语句,如果成功返回true,失败返回false;
  64. /// 
  65. /// 类似于UPDATE [USER] SET userID=@userIDC  WHERE userID=@userID
  66. /// 或delete from [user] where userID=@userID;
  67. /// 或者insert into [user] (userID, password, name) values (@userID,@password,@Name) ;
  68. /// 
  69. ///  SqlParameter[] sp = new SqlParameter[3];
  70. ///  sp[0] = new SqlParameter(user, SqlDbType.VarChar, 50);
  71. /// sp[0].Value = “www”;
  72. /// 
  73. /// 
  74. public bool EXESql( string sqlcmd, MySqlParameter[] sqlPara)
  75. {
  76. try
  77. {
  78. CreateConn();
  79. cmd = new MySqlCommand();
  80. cmd.Connection = conn;
  81. cmd.CommandType = CommandType.Text;
  82. cmd.CommandText = sqlcmd;
  83. foreach (MySqlParameter sp in sqlPara)
  84. {
  85. cmd.Parameters.Add(sp);
  86. }
  87. cmd.ExecuteNonQuery();
  88. CloseConn();
  89. return true ;
  90. }
  91. catch (Exception e)
  92. {
  93. return false ;
  94. }
  95. }
    1. }
  96. }

这里调用的代码这样写:

DataSet ds = sqlAccess.SelectDataSet(“select * from user”);

当然如果你使用DataSet还要加using System.Data;

连接字符串中为什么要加Allow Zero datetime  = true是因为在添加数据库数据时,

添加了错误的dateTime数据,所以mysql自动将其转为0000-00-00 00:00:00,所以在

DataSet ds = new DataSet();
sda.Fill(ds);

这里就会报异常,原因是不支持这种Date/Time。

要使用刚才的接口的话:

  1. {
  2. DataSet ds = sqlAccess.SelectDataSet( “select * from user” );
      1. Array alist = ds.Tables[0].Rows[0].ItemArray;
  3. foreach ( object o in alist)
  4. {
  5. label1.Text += o.ToString();
  6. }
  7. UpdateName();
  8. }
      1. private const string sql = “UPDATE USER SET userName=@userName  WHERE userID=@userID” ;
  9. private const string userName = “@userName” ;
  10. private const string userID = “@userID” ;
  11. private void UpdateName()
  12. {
  13. int i = 1;
  14. string name = “xxxx” ;
  15. MySqlParameter[] my =
  16. {
  17. new MySqlParameter(userName,MySqlDbType.String),
  18. new MySqlParameter(userID,MySqlDbType.Int32)
  19. };
  20. my[0].Value = name;
  21. my[1].Value = i;
  22. label2.Text = sqlAccess.EXESql(sql, my).ToString();
  23. }

刚才不久百度给我打了电话。我没有接到。之后拨通电话,发现是百度的总机。不知道要拨哪个分机,所以就挂掉了。
因为我参加了百度的笔试。所以认为可能是百度让我去参加面试。欣喜的将此事告诉了别人。
我:“我没有接起百度给我的面试电话。”
A:“你怎么知道百度是让你去面试?”
我:“我猜的。”
A:“那是百度看你的卷子看的崩溃了,他是想通知你以后不要浪费别人公司的草稿纸,不会答就不要去做!…”
我:“你的观点很有新意,我要写成blog!”
。。于是就有了这篇blog。据说blog是采用了传说中杀人于无形的流水帐式文笔。不知看过此blog的各位小同学中有没有谁吐血身亡。

主要是为了件T恤和免费的东西吃才去的。

不过在听别人的讲的过程中也有点点滴滴的体会,同时也扩展了自己的知识面。

RSpec这个是可以将文本语言转换为代码的工具。感觉挺新奇的。于是有了些想法:编程语言->中间语言->自然语言。似乎必须经历这一个过程。所以人们一味的创建自
然语言到程序代码的强制转换,似乎有些勉强。之所以是编程语言->中间语言->自然语言而不是编程语言<-中间语言<-自然语言.是因为其实有很多自然语言连人类自己
的都很难识别。所以更别说机器了。所以机器能识别的语言应该是自然语言的子集,而不是全集。

从Testing Scenario(测试场景)->自动化测试,其实我认为这里还是单箭头。利用刚才的RSpec这个工具,似乎可以达到这个效果。RSpec做的事
情说的直白点就是从文档到软件是转换。千古难题呀!

DW2的CEO的一句话“without software, we are
nothing.”细细想来,感触很多。感觉自己应该有第二门手艺,一门完全脱离计算机还能养活自己的手艺。

CISCO的人很想把Network与Application融合到一起。然后说了一句话:“Network is always in the middle.”

听了一个创业人所讲的创业经历:

1.做产品还是做开发。(其实这两者是不一样的,很多人都会编码,但是不会写文档,不会做界面。)

2.让少量的人做大量的事。这是一个产品化的过程。也是一个开始盈利的过程。

3.知道自己擅长什么。这个很关键。不过入行才几年的人的确不知道自己擅长什么。

这个类的名字叫huffman Tree,但是不仅仅是生成huffman Tree,因为Huffman树的生成要使用优先队列,也就是堆。stl中其实有这个的实
现。但是我机器里的vs2005这个堆的使用有点小bug(估计是stl中使用的就是数组存储,而且数组一旦固定大小,就再也无法改变,其实这样实现失去了堆的某些特
性。 _ 所以我还是自己实现了一下 _
。顺便练习下。)。刚开始的时候
就采用int作为编码的存储单元。后来发现huffman是可变长编码。所以使用int作为编码单元就失去了huffman的特性。于是寻找bit数组。找到了bit
set这个stl类,却发现这个是不可变的。无语。只得自己实现一个可变大小的 _ bit vector _

。然后近乎重写了这个Huffman的编码和解码。不过也不是很难。在这之间又陆陆续续的发现了一系列的bug和编译错误。对以后的编程大有启发。

  1. /* created by chico chen
  2. *  date 2008/10/25
  3. */
      1. #ifndef HUFFMAN_TREE
  4. #define HUFFMAN_TREE
  5. #include “Heap.h”
  6. #include “TreeNode.h”
  7. #include “BinaryTree.h”
  8. #include 
  9. #include “…/…/ArithmeticTest/ArithmeticTest/BITVector.h”
  10. using namespace std;
    1. // this class is used for the combin function in huffmanTree class.
  11. class IntCombin
  12. {
  13. public :
  14. static int Add( int i, int j)
  15. {
  16. return i+j;
  17. }
  18. };
    1. // this class for compare tree node
  19. template < class T>
  20. class TreeNodeCompare
  21. {
  22. public :
  23. static bool Up(TreeNode* d1, TreeNode* d2)
  24. {
  25. return Lt(d1->getData(),d2->getData());
  26. }
    1. static bool Eq(T& d1, T& d2)
  27. {
  28. if (d1 == d2)
  29. return true ;
  30. return false ;
  31. }
    1. static bool Gt(T& d1, T& d2)
  32. {
  33. if (d1 > d2)
  34. return true ;
  35. return false ;
  36. }
    1. static bool Lt(T& d1, T& d2)
  37. {
  38. if (d1 < d2)
  39. return true ;
  40. return false ;
  41. }
  42. };
    1. // this class is for storing huffman code.
  43. // bits and the length of bits
  44. class HuffmanCode
  45. {
  46. public :
  47. BITVector bits;
  48. int len;
  49. HuffmanCode()
  50. {
  51. len = 0;
  52. }
    1. HuffmanCode( const HuffmanCode & codes):bits(codes.bits)
  53. {
  54. len  = codes.len;
    1. }
    1. const HuffmanCode& operator=( const HuffmanCode & codes)
  55. {
  56. if ( this != &codes)
  57. {
  58. this ->len = codes.len;
  59. this ->bits = codes.bits;
  60. }
  61. return * this ;
  62. }
    1. ~HuffmanCode()
  63. {
    1. }
  64. };
    1. template < class T, class Cmp, class Combin>
  65. class HuffmanTree: public BinaryTree
  66. {
  67. private :
  68. // store the data, and sort it, then for building a huffman tree
  69. Heap<TreeNode* ,Cmp> huffmanQueue;
    1. const unsigned int mask;
  70. // the max number can be shifted, if it is unsigned int then it will be 32.
  71. const int maxShiftNum;
      1. TreeNode* initTree()
  72. // init the huffman tree
  73. {
  74. TreeNode * combinNode = NULL;
  75. T tempData;
  76. while (! this ->huffmanQueue.IsEmpty())
  77. {
  78. // fetch two small data and generate a large data
  79. TreeNode * node1 = this ->huffmanQueue.Top();
  80. combinNode = node1;
  81. this ->huffmanQueue.RemoveTop();
  82. if (! this ->huffmanQueue.IsEmpty())
  83. {
  84. TreeNode * node2 = this ->huffmanQueue.Top();
  85. this ->huffmanQueue.RemoveTop();
  86. tempData =  Combin::Add(node1->getData(),node2->getData());
      1. if (Cmp::Lt(node1->getData(),node2->getData()))
  87. {
  88. // here is comparing the data1 of node1 and the data2 of node2
  89. //  Cmp:Lt means ‘<’ and Cmp:Gt means ‘>’
    1. combinNode = new TreeNode(tempData,node1,node2);
  90. }
  91. else
  92. {
  93. combinNode = new TreeNode(tempData,node2,node1);
  94. }
  95. this ->huffmanQueue.Insert(combinNode);
  96. }
  97. else
  98. {
  99. break ;
  100. }
    1. }
  101. return combinNode;
  102. }
        1. // the final huffman code
  103. map<T,HuffmanCode> huffmanTable;
      1. void SelfEncode(TreeNode* subRoot,unsigned int bitcode, int num,map<T,HuffmanCode > &ht)
  104. // encoding the data from a huffman tree.
  105. // The left branch is 0, and the right branch is 1
  106. {
    1. if (subRoot != NULL)
  107. {
    1. if (subRoot->left == NULL && subRoot->right==NULL)
  108. {
  109. HuffmanCode hc;
  110. hc.bits.SetInt(bitcode,0,maxShiftNum-num);
  111. hc.len = maxShiftNum-num;
  112. ht[subRoot->getData()] = hc;
  113. return ;
  114. }
  115. else
  116. {
  117. if (num<=0)
  118. {
  119. throw “the huffman is too deep!” ;
  120. }
      1. SelfEncode(subRoot->left,bitcode,num-1,ht);
  121. bitcode = bitcode | (0x80000000 >> (maxShiftNum-num));
  122. SelfEncode(subRoot->right,bitcode,num-1,ht);
  123. }
  124. }
      1. }
      1. void DecodeFromTree(TreeNode* subRoot,BITVector& bits, int index, const int & len,vector& decode)
  125. // decoding the code. use the code to search the data from the huffmanTree.
  126. // here you can create you own map<code,data> deHuffmanTable.
  127. // but I can not analyze the space the table will use,
  128. // so I find the data by searching huffman tree
  129. {
  130. if (index == len)
  131. {
  132. if (subRoot->getLeft()==NULL && subRoot->getRight() == NULL)
  133. {
    1. decode.push_back(subRoot->getData());
  134. return ;
  135. }
  136. throw “code length is not match the bits length. Huffman Tree construct error.” ;
  137. }
  138. if (subRoot == NULL)
  139. {
  140. throw “decode error!” ;
    1. }
  141. else if (subRoot->getLeft() == NULL && subRoot->getRight() == NULL)
  142. {
    1. decode.push_back(subRoot->getData());
  143. return DecodeFromTree( this ->root,bits,index,len,decode);
  144. }
    1. if (bits.Get(index) == 0)
  145. {
  146. return DecodeFromTree(subRoot->getLeft(),bits,index+1,len,decode);
  147. }
  148. else if (bits.Get(index)==1)
  149. {
    1. return DecodeFromTree(subRoot->getRight(),bits,index+1,len,decode);
  150. }
  151. else
  152. {
  153. throw “code error!” ;
  154. }
      1. }
      1. unsigned int FindCodeFromTable(T& data)
  155. // find the data code from huffman table
  156. // may be not efficient.
  157. {
  158. return this ->huffmanTable[data];
  159. }
    1. public :
    1. HuffmanTree(T t[], int n):
  160. BinaryTree(),mask(0x80000000),maxShiftNum( sizeof (unsigned int )*8)
  161. // the array t type is T, and the number is n
  162. {
  163. if (n == 0)
  164. return ;
  165. TreeNode* node;
  166. for ( int i = 0; i < n; i++)
  167. {
  168. node = new TreeNode(t[i]);
  169. this ->huffmanQueue.Insert(node);
  170. }
  171. this ->root = initTree();
  172. }
    1. ~HuffmanTree()
  173. {
  174. // destroy
    1. }
      1. void SelfEncode()
  175. // convert the huffmanTree into huffmanTable
  176. // unsigned int code is 32 bits, so the huffman tree has only less than 33 layer.
  177. {
  178. string s= “” ;
    1. SelfEncode( this ->root,0,maxShiftNum, this ->huffmanTable);
    1. }
        1. void Decode(HuffmanCode& huffmanCode,vector& decode)
  179. // use bit to find the data node.
  180. {
    1. return DecodeFromTree( this ->root,huffmanCode.bits,0,huffmanCode.len,decode);
    1. }
    1. HuffmanCode Encode(T info[], int n)
  181. // n is size
  182. {
  183. HuffmanCode hc;
    1. for ( int i = 0; i < n; i++)
  184. {
    1. hc.bits.SetBitVector(((HuffmanCode) this ->huffmanTable[info[i]]).bits,hc.len,((HuffmanCode) this ->huffmanTable[info[i]]).len);
  185. hc.len +=((HuffmanCode) this ->huffmanTable[info[i]]).len;
  186. }
    1. return hc;
  187. }
      1. void PrintHuffmanTable()
  188. // print the huffman table
  189. // print the pair data<->code
  190. {
  191. int len = this ->huffmanTable.size();
  192. cout << “i/tdata/tcode/n” ;
  193. int count = 0;
  194. map<T,HuffmanCode>::iterator i= this ->huffmanTable.begin();
  195. for (; i != this ->huffmanTable.end(); i++)
  196. {
  197. cout << count++<< “/t” <<(*i).first<< “/t” ;
  198. (*i).second.bits.PrintfZeroOne(0,(*i).second.len);
  199. cout<<endl;
  200. }
    1. }
    1. };
      1. #endif

这个类设计方面还有些不足之处。比如encode方法

测试一下:

  1. int a[10] = {12,224,33,32,1,91,35,34,36,291};
  2. HuffmanTree< int ,TreeNodeCompare< int >,IntCombin> ht(a,10);
  3. ht.SelfEncode();
  4. ht.PrintHuffmanTable();
  5. ht.printTree();
  6. cout << endl;
  7. int info[] = {33,34,33};
  8. HuffmanCode hc = ht.Encode(info,3);
  9. hc.bits.PrintfZeroOne(0,hc.len);
  10. vector< int > code;
  11. ht.Decode(hc,code);
  12. ** for ** ( int i = 0; i != code.size();i++)
  13. {
    1. cout<<code[i]<<endl;
  14. }
    1. ** return ** 0;

其实c++里有bitset这个类,但是bitset使用时必须给定大小。例如

bitset<8> c;//这里必须在编码里写死,不能使用变量替代

c = 234;

我主要是用这个东西来存储可变长的huffman编码。所以这个类对我根本不能用。除非开始就给一个足够大的bitset。

所以我创建里一个可变长的bit vector用于存放Huffman编码。

在这里内部使用的是__int64,64位。当然根据实际需要可以将这个做为模板传入,不过现在还没有这样编码。

  1. /* created by chico chen
  2. *  date 2008/10/25
  3. */
  4. #ifndef BIT_VECTOR
  5. #define BIT_VECTOR
  6. #include 
  7. using namespace std;
      1. class BITVector
  8. {
  9. private :
  10. __int64 * bitarray;
  11. const int bits;
  12. const unsigned __int64 mask ;
  13. int size;
  14. void SetOne( int index); // x is 0
  15. void SetZero( int index); // x is 1
  16. void Larger();
    1. public :
  17. BITVector( void );
  18. void Set( int index, int x); // x is 0 or 1
  19. int Get( int index);
  20. int Size();
  21. void SetInt(unsigned int integer, int start, int len);
  22. void PrintfZeroOne( int start , int len); // print the unsigned it as 0 or 1
  23. void SetBitVector(BITVector & c, int start, int len);
  24. const BITVector& operator=( const BITVector& bitVector);
  25. explicit BITVector( const BITVector & bitVector);
    1. public :
  26. ~BITVector( void );
  27. };
  28. #endif

然后是bitVector.cpp文件

  1. /* created by chico chen
  2. *  date 2008/10/25
  3. */
  4. #include “StdAfx.h”
  5. #include “BITVector.h”
    1. BITVector::BITVector( void ):mask(0x8000000000000000),bits( sizeof ( __int64 )*8)
  6. {
  7. bitarray = new __int64 [1];
  8. memset(bitarray,0, sizeof ( __int64 ));
  9. size = 1;
  10. }
    1. BITVector::~BITVector( void )
  11. {
  12. size = 0;
  13. delete [] bitarray;
  14. }
    1. void BITVector::Set( int index, int x)
  15. {
  16. if (x == 0)
  17. {
  18. return SetZero(index);
  19. }
  20. else
  21. {
  22. return SetOne(index);
  23. }
  24. }
    1. void BITVector::SetZero( int index)
  25. {
  26. int innIndex = index/bits;
  27. int bitPos = index & (bits-1); // innIndex % 8
  28. if ( innIndex < size)
  29. {
  30. // vector maybe has enough space to store this .
  31. this ->bitarray[innIndex] = this ->bitarray[innIndex] & ~(mask >> bitPos);
  32. }
  33. else if (innIndex == size)
  34. {
  35. // should larger the size of bitarray
  36. // and innIndex must be the first bit of last char
    1. if (bitPos == 0)
  37. {
  38. // correct
  39. this ->Larger();
  40. this ->bitarray[innIndex] = this ->bitarray[innIndex] & ~(mask >> bitPos);
    1. }
  41. else
  42. {
  43. // error
    1. }
  44. }
  45. else
  46. {
  47. // there may be something error, or some code missing
    1. }
  48. }
      1. void BITVector::Larger()
  49. {
  50. __int64 * tempArray = new __int64 [size];
  51. memcpy(tempArray, this ->bitarray, sizeof ( __int64 )*size);
  52. delete [] this ->bitarray;
    1. this ->bitarray = new __int64 [size*2]; // may be error
  53. memset(bitarray,0, sizeof ( __int64 )size2);
  54. memcpy( this ->bitarray,tempArray, sizeof ( __int64 )*size);
  55. size = size*2;
  56. delete [] tempArray;
      1. }
    1. void BITVector::SetOne( int index)
  57. {
  58. int innIndex = index/bits; // you can use >>(bits-1)
  59. int bitPos = index % bits; // innIndex & (bits-1)
  60. if ( innIndex < size)
  61. {
  62. // vector maybe has enough space to store this .
  63. this ->bitarray[innIndex] = this ->bitarray[innIndex] | (mask >> bitPos);
  64. }
  65. else if (innIndex == size)
  66. {
  67. // should larger the size of bitarray
  68. // and innIndex must be the first bit of last char
    1. if (bitPos == 0)
  69. {
  70. // correct
  71. this ->Larger();
  72. this ->bitarray[innIndex] = this ->bitarray[innIndex] | (mask >> bitPos);
    1. }
  73. else
  74. {
  75. // error
    1. }
  76. }
  77. else
  78. {
  79. // there may be something error, or some code missing
    1. }
    1. }
    1. int BITVector::Get( int index)
  80. {
  81. if (index < size*bits)
  82. {
  83. int position = index & (bits-1); // % bits
  84. int innIndex = index/bits;
  85. __int64 i = this ->bitarray[innIndex] & (mask >> position);
  86. if (i == 0)
  87. {
  88. return 0;
  89. }
  90. else
  91. {
  92. return 1;
  93. }
  94. }
  95. throw “access out of the array” ;
  96. }
    1. int BITVector::Size()
  97. {
  98. return size*bits;
  99. }
    1. // int integer is 0x01010111
  100. // start is the start position of bitvector, and start starts zero
  101. // len is length of the number of bits you want set into bit array
  102. void BITVector::SetInt(unsigned int integer, int start, int len)
  103. {
  104. int finalPos = start + len;
  105. int i=start;
  106. int j = 0;
  107. int temp = 0;
  108. for (;i < finalPos; i++,j++)
  109. {
  110. temp = integer & (0x80000000 >> j);
  111. this ->Set(i,temp);
  112. }
  113. }
      1. void BITVector::PrintfZeroOne( int start, int len)
  114. {
  115. int finalPos = start+len;
  116. int temp = 0;
  117. for ( int i = start; i < finalPos; i++)
  118. {
  119. printf( “%d” , this ->Get(i));
  120. }
  121. }
    1. // start is where to insert bit vector c
  122. // len is the length of bits inserted
  123. // “start” is of this, and “len” is of c;
  124. void BITVector::SetBitVector(BITVector & c, int start, int len)
  125. {
    1. for ( int i = 0; i < len; i++)
  126. {
  127. this ->Set(start+i,c.Get(i));
  128. }
    1. }
    1. // copy construct
  129. BITVector::BITVector( const BITVector & bitVector):mask(0x8000000000000000),bits( sizeof ( __int64 )*8)
  130. {
  131. this ->size = bitVector.size;
  132. this ->bitarray = new __int64 [ this ->size];
  133. memcpy( this ->bitarray,bitVector.bitarray, sizeof ( __int64 )*bitVector.size);
  134. }
    1. const BITVector& BITVector::operator=( const BITVector& bitVector)
  135. {
  136. if ( this != &bitVector)
  137. {
  138. this ->size = bitVector.size;
  139. delete [] this ->bitarray;
  140. this ->bitarray = new __int64 [ this ->size];
  141. memcpy( this ->bitarray,bitVector.bitarray, sizeof ( __int64 )* this ->size);
  142. }
  143. return * this ;
  144. }

因为vs2005中c++的Heap构造 _ 有些问题 _
,所以才重写了heap类。

不知道vs2008中这个是不是个bug。

  1. /* created by chico chen
  2. *  date 2008/10/25
  3. */
  4. template< class T, class Cmp>
  5. class Heap
  6. {
  7. private :
  8. vector heap;
  9. void ShiftDown( int index)
  10. {
  11. while (!IsLeaf(index))
  12. {
  13. int l = Lchild(index);
  14. int r = Rchild(index);
  15. if (r != -1)
  16. {
  17. if (Cmp::Up(heap[r],heap[l]))
  18. {
  19. // put the up node to the left
  20. swap(heap[l],heap[r]);
  21. }
  22. }
  23. if (Cmp::Up(heap[l],heap[index]))
  24. {
  25. // up the left child
  26. swap(heap[l],heap[index]);
  27. index = l;
  28. }
  29. else
  30. {
  31. break ;
  32. }
  33. }
    1. }
  34. void ShiftUp( int index)
  35. {
  36. int parent = -1;
  37. while (index != 0)
  38. {
  39. parent = Parent(index);
  40. if (Cmp::Up(heap[index],heap[parent]))
  41. {
  42. swap(heap[index],heap[parent]);
  43. index = parent;
  44. }
  45. else
  46. {
  47. break ;
  48. }
  49. }
    1. }
  50. void ReHeapAll()
  51. {
  52. for ( int i=Parent(heap.size()-1); i>= 0; i–)
  53. {
  54. ShiftDown(i);
  55. }
  56. }
  57. void ReHeapOne( int index)
  58. // set one prior and re-position the index node
  59. {
  60. T data = heap[index];
  61. ShiftDown(index);
  62. if (Cmp::Eq(data,heap[index]))
  63. {
  64. ShiftUp(index);
  65. }
  66. }
  67. int Parent( int index)
  68. // parent node of the index node
  69. {
  70. return (index-1)/2;
  71. }
  72. int Lchild( int index)
  73. // Left child of the index node
  74. {
  75. if (!IsLeaf(index))
  76. return index*2+1;
  77. return -1;
  78. }
  79. int Rchild( int index)
  80. // Right child of the index node
  81. {
  82. if (!IsLeaf(index))
  83. {
  84. int r= index*2+2;
  85. if (r<heap.size())
  86. return r;
  87. }
  88. return -1;
  89. }
    1. int IsLeaf( int index)
  90. {
  91. assert(index < heap.size());
  92. if (heap.size() == 1)
  93. return true ;
  94. int lastNode = Parent(heap.size()-1);
  95. return lastNode < index;
  96. }
    1. int FindData(T& data)
  97. {
  98. int len = heap.size();
  99. for ( int i = 0; i < len; i++)
  100. {
  101. if (Cmp::Eq(data,heap[i]))
  102. {
  103. return i;
  104. }
  105. }
  106. return -1; // can not find the data
  107. }
    1. void printTree( int index, int count)
  108. {
  109. if (index < heap.size() && index >=0)
  110. {
    1. printTree(Rchild(index),count+4);
  111. for ( int i = 0; i < count; i++)
  112. {
  113. cout << " " ;
  114. }
  115. cout <<heap[index]<<endl;
  116. printTree(Lchild(index),count+4);
  117. }
  118. }
  119. public :
  120. Heap()
  121. {
  122. heap = vector();
  123. }
  124. ~Heap()
  125. {
  126. // heap destroyed
  127. }
  128. bool IsEmpty()
  129. {
  130. return heap.size() == 0;
  131. }
        1. void Insert(T& data)
  132. {
  133. heap.push_back(data);
  134. ShiftUp(heap.size()-1);
  135. }
  136. void Delete( int index)
  137. {
  138. int last = heap.size()-1;
  139. if (index>=0 && index <= last)
  140. {
    1. swap(heap[index],heap[last]);
  141. heap.pop_back();
  142. ReHeapOne(index);
  143. }
  144. }
  145. void Delete(T& data)
  146. {
  147. int index = FindData(data);
  148. if (index != -1)
  149. Delete(index);
  150. }
      1. void RemoveTop()
  151. {
    1. if (!IsEmpty()&&heap.size()>1)
  152. {
  153. swap(heap[0],heap[heap.size()-1]);
  154. heap.pop_back();
  155. ShiftDown(0);
  156. }
  157. else if (heap.size() == 1)
  158. {
  159. heap.pop_back();
  160. }
    1. }
  161. T& Top()
  162. {
  163. return heap[0];
  164. }
    1. void Print()
  165. {
  166. printTree(0,1);
  167. }
        1. };
0%