帐前卒专栏

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

近来看到有书上的构造函数上写有explicit的关键词,出于好奇查个究竟,why?

原因很简单:

当构造函数的参数只有一个的时候,编译器会默认将

Type obj=0转换为Type obj(0)

或者obj = Type(0)

当然这还不局限于整数等情况

错误例子1:

class MyClass

{

MyClass();//这个是必须的

MyClass (int a);

};

在其他函数中这样调用

{

MyClass a; //如果没有默认构造函数这里就会出错

int ac = 3;

a = 4;//这里想写ac=4

}

那么这里就会有问题,因为编译器隐式转换为a = MyClass(4);记住这里的=可是基于bit的赋值,也是编译器默认提供的

当然如果你有写operator =()这个函数,那就另当别论。

错误例子2:

class MyClass

{

MyClass (int a);

};

其他函数里这样调用

{

MyClass a =4;//这里隐式转换为MyClass a(4)

}

所以很容易照成错误。而且这个错误不是编译错误,而是运行时可能的bug。

所以为了避免让大家犯错误,我们只有小心的设计自己的类

class MyClass

{

explicit MyClass (int a);

};

这样如果程序中再调用MyClass a =4;这样语句,程序就会报编译错误。

其实我们写程序不光为了让别人看懂,程序运行正确,还要想方设法的让大家少犯错误。

当然如果你的构造函数必须多于一个参数,其实就没有必要用explicit关键字了。

explicit的关键字只构造函数中带一个参数的情况起作用。其书面语的作用为:禁止单参构造函数的隐式转换。

机器人是作为单一个体还是有统一精神?

和“I robot”影片不同是,此片中的机器人都有自己独立的性格。可以完全不服从最高领导机器的统治。而I
robot中的不同,只有偶尔的一个机器人变异才使得机器拥有丰富的表情和情感。

另外发现Wall-E的鲁棒性非常好。在经历短路,压挤之后,换个主板仍能很好的工作。不过各个机器人的主板都不相同,看来各个机器人都有自己的用途。

Wall-E的目标更正和情感驱动做得很好。Wall-
E是700年前古老的机器人,竟然进化到能够明白自己想要做什么。这和一般的机器人不同。其他的机器人的指令要求输入,机器人才知道要干什么。Wall-
E已经强大到可以自我更改程序目标,做自己想做的事情。这比Captain机器人还要高级。因为Captain机器人竟然还遵循着700年前的决定。

一定要给机器人做一个停止按钮,一旦它不能正常工作,马上可以通过此按钮将它终止掉。

有情感不服从命令的机器人,我想大概都是因为程序bug导致的。正常的机器人循规蹈矩,只有少数编码不正确的机器人才能打破思维定势。难道人工智能质的突破要靠程序的
中的bug吗?

每个人都是文雀。

停留这里,是因为想呆在这里,

飞离这里,是因为想去其他地方,

不要限制自由,想去那里就应该能去哪里,

不论现在的生活是安逸还是贫苦。

我不清楚盗亦有道要不要提倡,因为盗已经偏离了道德准则。

盗亦有道这个很搞笑的成语,是老祖宗提出的悖论。

幸好林熙蕾是个ppmm,如果换成恐龙妹,我不认为那群小偷也会有“盗亦有道”。

这说明美人计是一个很好用的计策,放之四海皆成功。(当然这要排除断背和女子这两种情况)

江山代有才人出,过去的盗圣,现在可不一定是。

所以好汉不提当年勇。

提当年勇的好汉当然也是好汉,不过是当年的好汉,不一定是现在的好汉。

几乎没有人能够做到十全十美,正如标题一样

其实十全九美已经是较完美的结局了。

影片结局有些让人遗憾,但是不能奢求每一个电影的结局都是大圆满。传说悲剧的结局远比喜剧结局给人留下的印象要深。喜剧往往一笑而过,隔日或许只能记得最搞笑的情节。

但是这影片也算不上悲剧,只是略有悲情而已。

最后合棺一幕有些意思,不管平民还是皇帝,最后还不都是枯尸一具。

下面摘录主题曲《梨花香》,歌词写得不错,很有诗意。

笑看世间痴人万千
白首同倦实难得见
人面桃花是谁在扮演

事过境迁故人难见
旧日黄昏映照新颜
相思之苦谁又敢直言

梨花香 却让人心感伤
愁断肠千杯酒解思量
莫相望旧时人新模样思望乡

事过境迁故人难见
旧日黄昏映照新颜
相思之苦谁又敢直言

为情伤世间事皆无常
笑沧桑万行泪化寒窗
勿彷徨脱素裹着春装忆流芳

笑我太过痴狂相思夜未烊
独我孤芳自赏残香

梨花香 却让人心感伤
愁断肠千杯酒解思量
莫相望旧时人新模样思望乡
为情伤世间事皆无常
笑沧桑万行泪化寒窗
勿彷徨脱素裹着春装忆流芳

生活在最底层的人们,不被人关注,貌似柔弱,但是有顽强的生命力。

不论自己如何,总有比自己更弱小的人需要保护。

不论如何,顽强的生存下去,总是会有希望。

生命中与很多人相遇相离,每个人都有自己的方向。

一起上路还是分手离别,本无需在意太多。

青苔是不开花的。流浪者对小女孩的那句话意味深长:“你是花!”。

我的系统是虚拟机上的ubuntu8

1。先去 http://www.postgresql.org 那里下个postgreSQL
core 8.3.
2.使用命令tar -xvf postgreSQL-8.3.3.tar.bz2   解压

3.去那个解压的文件夹,使用./configure 命令,它将自动检查系统配置

4.很不幸得是报了一个"c cannot output the executable file"

5.然后在网上找了找资料,发现没有升级libc所以使用命令:sudo apt-get install libc6-dev gcc g++

6再运行"./configure",却报了readline library is not found,如果这个错误你能解决最好,还有可能报zlib is
not found

7.不幸的是我找了2个多小时,下载了无数相关的包,最后以readline5-dev包不能正常安装告终。

8.所以没有办法,只好这样运行./configure --without-readline --without-zlib

9然后make

10下面命令是要加sudo的
make install
adduser postgres
mkdir /usr/local/pgsql/data
chown postgres /usr/local/pgsql/data
到了这里,我们要创建logfile 文件然后把它拷贝到 /usr/local/pgsql/data/ (好像不拷贝也可以,大家可以试试)
然后切换用户sudo - postgres
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data >logfile 2>&1 &
/usr/local/pgsql/bin/createdb test
/usr/local/pgsql/bin/psql test

最后,你能看到sql 交互界面…大功告成…

下面是自己写的英文安装手册, 英语语法错误多多指正(非大小写)。

how to install pgSQL in ubuntu

I installed Ubuntu 8.04 in VMMachine.
1. goto the http://www.postgresql.org to
download postgreSQL core 8.3.
2. tar -xvf postgreSQL-8.3.3.tar.bz2   (I don’t know your downloaded file
name. You can change it)
3. go the unpacked folder then “./configure”
4. it will check the environment of your computer.
5. Unluck, it showed error to me. IF it report like “c cannot output the
executable file”, then "sudo apt-get install

libc6-dev gcc g++
6. The run “./configure” again. It report “readline library is not found.”.
7. ./configure --without-readline --without-zlib
8. make

sudo
make install
adduser postgres
mkdir /usr/local/pgsql/data
chown postgres /usr/local/pgsql/data
create a file called logfile and copy it to /usr/local/pgsql/data/
sudo - postgres
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data >logfile 2>&1 &
/usr/local/pgsql/bin/createdb test
/usr/local/pgsql/bin/psql test

在网上搜索了很多红黑树的资源,发现自己看代码的能力还是有些欠缺。很多都看不懂,后来找到一篇英文红黑树文献,终于弄明白了红黑树的删除插入是怎么做的。但是那片文
献好像还有些漏洞,其中有一种删除情况,他并没有考虑到。如果大家想看的话可以搜索下 “red-black trees” ,由 prof. Lyn
Turbak所写。因为时间关系,插入算法只是实现了非CLR算法。删除算法我也不知道叫什么名字(文献里没有讲)。但是删除结果依旧符合红黑树。

建立红黑树节点的时候,考虑到因为经常要和一个节点的父亲节点打交道,所以采用了在节点里添加父亲节点的指针的方法。这样即方便也提高效率。另外也好调试。如果一味采
用递归…估计人会看疯掉的。插入的时候,采用的是先插入删除的时候红色节点,然后在判断是否违反红红条件。违反的话就左旋右旋进行调整。否则就插入成功。删除的时候
先删除节点,这个过程和删除二叉查找树节点一致。删除时要看真正要删除的节点是否是根节点,是否是黑色节点。因为红色节点和根节点删除不会调整树形。如果删除的是黑色
节点,那么要看替换他的节点(这里的替换一定是左子树树根,因为如果有右子树,那么被删除的也不会是这个节点,记住二叉查找树的删除过程)是否是黑色节点(这里如果左
子树为空,那他也是黑色节点)。如果是黑色节点,那么一定要调整树的结构,否则就直接染色。调整树结构时要考虑的情况就非常多了。一共有9种情况需要考虑。

下面是代码部分,删除时如何调整在代码注释中。至于insert操作,看看文献就应该会做了。

  1. /*
  2. * create RBNode class for construction RBTree
  3. * create by chico chen
  4. * date: 2008/09/04
  5. * 如需转载注明出处
  6. */
    1. template< class T>
  7. #define RED 0
  8. #define BLACK 1
  9. class RBNode
  10. {
  11. public :
    1. T data;
  12. RBNode* left;
  13. RBNode* right;
  14. RBNode* parent;
  15. int color;
    1. RBNode(T& data)
  16. {
  17. this ->data = data;
  18. left = NULL;
  19. right = NULL;
  20. parent = NULL;
  21. color = RED;
  22. }
  23. RBNode(T& data, RBNode* left, RBNode* right, RBNode* parent)
  24. {
  25. this ->data = data;
  26. this ->left = left;
  27. this ->right = right;
  28. this ->parent = parent;
  29. color = RED;
  30. }
    1. ~RBNode()
  31. {
  32. this ->left = this ->right = this ->parent = NULL;
  33. color = RED;
  34. }
  35. };

下面是红黑树代码

  1. /*
  2. * this is red-black-tree code
  3. * this code is not efficent in inserting
  4. * create by chico chen
  5. * date: 2008/09/04
  6. * 如需转载注明出处
  7. */
    1. #include “RBNode.h”
    1. template< class T>
  8. class RBTree
  9. {
    1. private :
  10. RBNode* root;
  11. public :
  12. RBTree()
  13. {
  14. this ->root = NULL;
  15. }
  16. ~RBTree()
  17. {
  18. clearTree( this ->root);
  19. }
        1. void print()
  20. {
  21. print( this ->root,0);
  22. }
            1. void insert(T& data)
  23. {
    1. RBNode* node = new RBNode(data);
  24. insertNode(node);
  25. }
    1. void deleteKey(T& data)
  26. {
  27. deleteNode(data);
  28. }
      1. bool RBTreeTest()
  29. {
  30. try
  31. {
  32. getBlackNum( this ->root);
    1. }
  33. catch (…)
  34. {
  35. return false ;
  36. }
  37. return true ;
  38. }
    1. private :
      1. void print(RBNode* subRoot, int num)
  39. {
  40. if (subRoot != NULL)
  41. {
  42. print(subRoot->right,num+3);
  43. for ( int i = 0; i < num; i++)
  44. {
  45. cout << " " ;
  46. }
  47. cout << subRoot->data<< “(” <color<< “)” <<endl;
  48. print(subRoot->left,num+3);
  49. }
  50. }
    1. void clearTree(RBNode* subRoot)
  51. {
  52. if (subRoot == NULL)
  53. return ;
  54. clearTree(subRoot->left);
  55. clearTree(subRoot->right);
  56. delete subRoot;
  57. }
    1. RBNode* deleteMin(RBNode* subRoot,RBNode** parent)
  58. {
    1. while (subRoot != NULL)
  59. {
  60. parent = &subRoot;
  61. if (subRoot->right != NULL)
  62. {
  63. subRoot = subRoot->right;
  64. }
  65. else
  66. {
  67. break ;
  68. }
  69. }
  70. return subRoot;
  71. }
    1. void deleteNode(T& data)
  72. {
  73. if (root == NULL)
  74. {
  75. throw “Empty tree” ;
  76. }
  77. RBNode* subRoot = root;
  78. while (subRoot != NULL)
  79. {
  80. if (subRoot->data > data)
  81. {
  82. subRoot = subRoot->left;
  83. }
  84. else if (subRoot->data < data)
  85. {
  86. subRoot = subRoot->right;
  87. }
  88. else
  89. {
  90. // find the data
  91. // use the midOrder last one which is before the data node to replace
  92. RBNode* inParent = subRoot;
  93. RBNode* deleteNode = deleteMin(subRoot->left,&inParent);
  94. RBNode* realDelete = NULL;
  95. if (deleteNode != NULL)
  96. {
  97. subRoot->data = deleteNode->data; // copy
  98. realDelete = deleteNode;
  99. //real delete
  100. }
  101. else
  102. {
  103. realDelete = subRoot;
  104. //real delete
  105. }
  106. if (realDelete->parent == NULL)
  107. {
  108. // delete root
  109. delete realDelete;
  110. }
  111. else
  112. {
  113. // nothing at realDelete->right
  114. RBNode* parent = realDelete->parent;
  115. RBNode* subATree = NULL;
  116. if (parent->left == realDelete)
  117. {
  118. parent->left = realDelete->left;
  119. }
  120. else
  121. {
  122. parent->right = realDelete->left;
  123. }
  124. subATree = realDelete->left;
  125. if (realDelete->left != NULL)
  126. {
  127. realDelete->left->parent = parent;
  128. }
  129. int color = realDelete->color;
  130. delete realDelete;
  131. if (color == BLACK &&
  132. (subATree == NULL || subATree->color == BLACK))
  133. {
      1. deleteRebuild(subATree,parent);
  134. }
  135. else if (color == BLACK && subATree->color == RED)
  136. {
  137. subATree->color = BLACK;
  138. }
  139. else
  140. {
  141. // do nothing
  142. }
  143. break ;
  144. }
    1. }
  145. }
  146. }
      1. /* delete them if you want
  147. //     x®                c®
  148. //     /  /                /  /
  149. //   `a(b) b(b) -->     x(b)   b(b)
  150. //         /            /
  151. //        c®         a(b)
  152. // LRL means L-> double black is at left, and rotate is RL
  153. RBNode* LRLCaseA(RBNode* x)
  154. {
  155. RLRotate(x,x->right,x->right->left);
  156. x->color = BLACK;
  157. return x->parent;
    1. }
      1. //     x®                 b®
  158. //     /  /                 /  /
  159. //   `a(b) b(b)   -->    x(b)   c(b)
  160. //          /             /
  161. //           c®       a(b)
  162. RBNode* LLLCaseA(RBNode* x)
  163. {
  164. RRRotate(x,x->right);
  165. x->color = BLACK;
  166. x->parent->color = RED;
  167. x->parent->right->color = BLACK;
  168. return x->parent;
  169. }
    1. //     x®                b®
  170. //     /  /                /  /
  171. //   b(b) `a(b)–>       c(b) x(b)
  172. //    /                         /
  173. //  c®                        a(b)
  174. RBNode* RLLCaseA(RBNode* x)
  175. {
  176. LLRotate(x,x->left);
  177. x->color = BLACK;
  178. x->parent->color = RED;
  179. x->parent->left->color = BLACK;
  180. return x->parent;
  181. }
      1. //     x®                c®
  182. //     /  /                /  /
  183. //   b(b) `a(b)–>       b(b) x(b)
  184. //    /                         /
  185. //    c®                        a(b)
  186. RBNode* RLRCaseA(RBNode* x)
  187. {
  188. LRRotate(x,x->left,x->left->right);
  189. x->color = BLACK;
    1. return x->parent;
  190. }
      1. //     x®                     x(b)
  191. //     /  /                     /  /
  192. //   `a(b) c(b)        ->     a(b) c®
  193. //         /   /                  /   /
  194. //        d(b)  e(b)            d(b)  e(b)
  195. RBNode* LCaseB(RBNode* x)
  196. {
  197. x->color = BLACK;
  198. x->right->color = RED;
  199. }
    1. //     x®                     x(b)
  200. //     /  /                     /  /
  201. //    c(b) `a(b)       ->     c® a(b)
  202. //   /   /                   /   /
  203. // d(b)  e(b)              d(b)  e(b)
  204. RBNode* RCaseB(RBNode* x)
  205. {
  206. x->color = BLACK;
  207. x->left->color = RED;
  208. }
    1. //     x(b)                    c(b)
  209. //     /  /                    /  /
  210. //  `a(b)  c®      ->     x®  e(b)
  211. //        /   /             /  /
  212. //       d(b)  e(b)      `a(b)  d(b)
  213. RBNode* LCaseC(RBNode* x)
  214. {
  215. RRRotate(x,x->right);
  216. x->color = RED;
  217. x->parent->color = BLACK;
  218. return  x->parent;
  219. }
    1. //     x(b)                    c(b)
  220. //     /  /                    /  /
  221. //   c® `a(b)     ->       d(b) x®
  222. //   /   /                        /  /
  223. //  d(b)  e(b)                  e(b) `a(b)
  224. RBNode* RCaseC(RBNode* x)
  225. {
  226. LLRotate(x,x->left);
  227. x->color = RED;
  228. x->parent->color = BLACK;
  229. return  x->parent;
  230. }
  231. */
    1. bool isBlack(RBNode* node)
  232. {
    1. if (node == NULL || node->color == BLACK)
  233. return true ;
  234. return false ;
  235. }
    1. void rebuild(RBNode* node)
  236. {
  237. if (node->parent->data > node->data)
  238. {
  239. node->parent->left = node;
  240. }
  241. else
  242. {
  243. node->parent->right = node;
  244. }
  245. }
      1. /*
  246. * There are 9 cases we will meet. The cases of the double black node at the right is ignored.
  247. * (b) means black node, (db) means double black node, ® means red node
  248. * 1.    (b)              2   (b)           3 (b)
  249. *      /   /                 /  /            /  /
  250. *    (db)  (b)             (db)  (b)       (db)  (b)
  251. *          /  /                  / /             / /
  252. *         (b)  (b)             ®  (b)        (b)  ®
  253. * 4.    (b)              5   (b)           6 ®
  254. *      /   /                 /  /            /  /
  255. *    (db)  (b)             (db)  ®       (db)  (b)
  256. *          /  /                  / /             / /
  257. *         ®  ®             (b)  (b)        (b)  (b)
  258. * 7.    ®              8   ®           9 ®
  259. *      /   /                 /  /            /  /
  260. *    (db)  (b)             (db)  (b)       (db)  (b)
  261. *          /  /                  / /             / /
  262. *         ®  (b)             (b)  ®        ®  ®
  263. * case 1,6: up the black, if the parent is black then call the function again until the
  264. * double black node is root, else blacken the parent.
  265. * case 2,4,7,9: call the RLRotate, if the parent of the double
  266. * node is black, up the black and call the function again, else
  267. * blacken the parent.
  268. * case 3,8: call the LLRotate, the same as case 2.
  269. * case 5: call LLRotate, change as    (b)   then end.
  270. *                                    /   /
  271. *                                  (b)    (b)
  272. *                                  / /
  273. *                                (b)  ®
  274. */
  275. void deleteRebuild(RBNode* node,RBNode* parent)
  276. {
  277. if (parent == NULL)
  278. {
  279. // root, delete the black
  280. return ;
  281. }
  282. if (parent->left == node)
  283. {
  284. RBNode* brother = parent->right;
  285. RBNode* nephewA = brother->left;
  286. RBNode* nephewB = brother->right;
    1. if (isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
  287. {
  288. // case 1,6
  289. brother->color = RED;
  290. if (parent->color == BLACK)
  291. {
  292. deleteRebuild(parent,parent->parent);
  293. }
  294. else
  295. {
  296. parent->color = BLACK;
  297. return ;
  298. }
    1. }
    1. else if (!isBlack(nephewA))
  299. {
  300. // case 2,4,7,9
  301. RBNode* tempRoot = RLRotate(parent,brother,nephewA);
  302. // rebuild
  303. rebuild(tempRoot);
    1. }
  304. else if (!isBlack(nephewB))
  305. {
  306. // case 3,8
  307. RBNode* tempRoot = RRRotate(parent,brother);
  308. rebuild(tempRoot);
  309. nephewB->color = BLACK;
  310. brother->color = RED;
  311. }
  312. else if (!isBlack(brother))
  313. {
  314. // case 5
  315. RBNode* tempRoot = RRRotate(parent,brother);
  316. rebuild(tempRoot);
  317. brother->color = BLACK;
  318. nephewA->color = RED;
  319. return ;
  320. }
  321. else
  322. {
  323. // unknown
  324. throw “none excption, about there is no red or black” ;
  325. }
    1. if (parent->color == BLACK)
  326. {
  327. // case 2,3,4
  328. deleteRebuild(parent,parent->parent);
  329. }
  330. else
  331. {
  332. // case 7,8,9
  333. parent->color = BLACK;
  334. }
    1. }
  335. else
  336. {
  337. RBNode* brother = parent->left;
  338. RBNode* nephewA = brother->right;
  339. RBNode* nephewB = brother->left;
    1. if (isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
  340. {
  341. brother->color = RED;
  342. if (parent->color == BLACK)
  343. {
  344. deleteRebuild(parent,parent->parent);
  345. }
  346. else
  347. {
  348. parent->color = BLACK;
  349. return ;
  350. }
  351. }
  352. else if (!isBlack(nephewA))
  353. {
  354. RBNode* tempRoot = LRRotate(parent,brother,nephewA);
  355. // rebuild
  356. rebuild(tempRoot);
    1. }
  357. else if (!isBlack(nephewB))
  358. {
  359. RBNode* tempRoot = LLRotate(parent,brother);
  360. rebuild(tempRoot);
  361. nephewB->color = BLACK;
  362. brother->color = RED;
  363. }
  364. else if (!isBlack(brother))
  365. {
  366. RBNode* tempRoot = LLRotate(parent,brother);
  367. rebuild(tempRoot);
  368. nephewA->color = RED;
  369. brother->color = BLACK;
  370. return ;
  371. }
  372. else
  373. {
  374. throw “none excption, about there is no red or black” ;
  375. }
    1. if (parent->color == BLACK)
  376. {
  377. deleteRebuild(parent,parent->parent);
  378. }
  379. else
  380. {
  381. parent->color = BLACK;
  382. }
    1. }
    1. }
      1. void insertNode(RBNode* node)
  383. {
    1. if (root == NULL)
  384. {
  385. root = node;
  386. node->color = BLACK;
  387. return ;
  388. }
  389. RBNode* subRoot = root;
  390. RBNode* insertPoint = NULL;
  391. while (subRoot!=NULL)
  392. {
  393. insertPoint = subRoot;
  394. if (subRoot->data > node->data)
  395. {
  396. // insert left
  397. subRoot = subRoot->left;
    1. }
  398. else if (subRoot->data < node->data)
  399. {
  400. subRoot = subRoot->right;
  401. }
  402. else
  403. {
  404. throw “same key” ;
  405. }
  406. }
      1. if (insertPoint->data > node->data)
  407. {
  408. insertPoint->left = node;
  409. }
  410. else
  411. {
  412. insertPoint->right = node;
  413. }
  414. node->parent = insertPoint;
      1. insertRebuild(node);
    1. }
    1. // return the subRoot
  415. //        a                   b
  416. //       /                  /   /
  417. //      b        ->        c     a
  418. //     /
  419. //    c
  420. RBNode* LLRotate(RBNode* a, RBNode* b)
  421. {
  422. if (b->right != NULL)
  423. {
  424. b->right->parent = a;
    1. }
  425. a->left = b->right;
  426. b->right = a;
  427. b->parent = a->parent;
  428. a->parent = b;
  429. return b;
  430. }
    1. // return the subRoot
  431. //        a                      b
  432. //          /                  /   /
  433. //            b        ->     a     c
  434. //              /
  435. //                c
  436. RBNode* RRRotate(RBNode* a, RBNode* b)
  437. {
  438. if (b->left != NULL)
  439. {
  440. b->left->parent = a;
    1. }
  441. a->right = b->left;
  442. b->left = a;
  443. b->parent = a->parent;
  444. a->parent = b;
      1. return b;
  445. }
      1. // return the subRoot
  446. //        a                      c
  447. //          /                  /   /
  448. //            b        ->     a     b
  449. //           /                 /
  450. //          c                   d
  451. //         /
  452. //        d
  453. RBNode* RLRotate(RBNode* a, RBNode* b, RBNode* c)
  454. {
    1. if (c->right != NULL)
  455. {
  456. c->right->parent = b;
    1. }
  457. b->left = c->right;
  458. c->right = b;
  459. b->parent = c;
  460. if (c->left != NULL)
  461. {
  462. c->left->parent = a;
    1. }
  463. a->right = c->left;
  464. c->left = a;
  465. c->parent = a->parent;
  466. a->parent = c;
    1. return c;
  467. }
    1. // return the subRoot
  468. //        a                      c
  469. //       /                     /   /
  470. //      b              ->     b     a
  471. //       /                         /
  472. //        c                       d
  473. //         /
  474. //          d
  475. RBNode* LRRotate(RBNode* a, RBNode* b, RBNode* c)
  476. {
  477. if (c->left != NULL)
  478. {
  479. c->left->parent = b;
      1. }
  480. b->right = c->left;
  481. c->left = b;
  482. b->parent = c;
  483. if (c->right!= NULL)
  484. {
  485. c->right->parent = a;
    1. }
  486. a->left = c->right;
  487. c->right = a;
  488. c->parent = a->parent;
  489. a->parent = c;
    1. return c;
  490. }
    1. // node is not the root
  491. void insertRebuild(RBNode* node)
  492. {
  493. RBNode* parent = NULL;
  494. RBNode* grandParent = NULL;
  495. while (node->parent != NULL)
  496. {
  497. parent = node->parent;
    1. if (parent->color == RED) // here means there must be a grandparent
  498. {
  499. grandParent = parent->parent;
  500. grandParent->color = BLACK;
    1. if (grandParent->left == parent)
  501. {
  502. if (parent->left == node)
  503. {
  504. //LLRotate
  505. node->color = BLACK;
  506. node = LLRotate(grandParent,parent);
    1. }
  507. else
  508. {
  509. //LRRotate
  510. parent->color = BLACK;
  511. node = LRRotate(grandParent,parent,node);
    1. }
    1. }
  512. else
  513. {
    1. if (parent->left == node)
  514. {
  515. //RLRotate
  516. parent->color = BLACK;
  517. node = RLRotate(grandParent,parent,node);
  518. }
  519. else
  520. {
  521. //RRRotate
  522. node->color = BLACK;
  523. node = RRRotate(grandParent,parent);
  524. }
  525. }
  526. }
  527. else
  528. {
  529. break ;
  530. }
  531. }
    1. if (node->parent == NULL)
  532. {
  533. node->color = BLACK;
  534. this ->root = node;
  535. }
  536. else
  537. {
  538. rebuild(node);
  539. /*if(node->parent->data > node->data)
  540. {
  541. node->parent->left = node;
  542. }
  543. else
  544. {
  545. node->parent->right = node;
  546. }*/
  547. }
  548. }
          1. int getBlackNum(RBNode* subRoot)
  549. {
  550. if (subRoot == NULL)
  551. {
  552. return 1;
  553. }
  554. int left = getBlackNum(subRoot->left);
  555. int right = getBlackNum(subRoot->right);
  556. if (left != right)
  557. {
  558. throw “wrong” ;
  559. }
  560. if (subRoot->color == BLACK)
  561. {
    1. return 1+left;
  562. }
  563. else
  564. {
  565. return left;
  566. }
    1. }
  567. };

近来看到小李子写了篇blog,题目为返回值优化。

文章如下。

return Integer(left.i+right.i); //创建一个临时对象并返回他,不会调用析构函数,效率高。
Interger tmp(left.i+right.i);
return tmp;              //创建了局部对象,有析构函数。

————————————————————————————————

这里感觉有些诡异。

于是编写了简单的程序

  1. // TempClassDestroy.cpp : Defines the entry point for the console application.
  2. //
    1. #include “stdafx.h”
  3. #include 
  4. using namespace std;
  5. class A
  6. {
  7. private :
  8. int a;
  9. public :
  10. A( int a)
  11. {
  12. this ->a = a;
  13. }
  14. ~A()
  15. {
  16. cout << “AA:” <<a<<endl;
  17. }
  18. };
      1. A& foo1( int c)
  19. {
  20. return A©;
  21. }
      1. A foo2( int c)
  22. {
  23. return A©;
  24. }
    1. A foo3( int c)
  25. {
  26. A a©;
  27. return a;
  28. }
  29. A& foo4( int c)
  30. {
  31. A a©;
  32. return a;
  33. }
  34. int _tmain( int argc, _TCHAR* argv[])
  35. {
  36. foo1(1);
  37. cout << “foo1” <<endl;
  38. foo2(2);
  39. cout << “foo2” <<endl;
  40. foo3(3);
  41. cout << “foo3” <<endl;
  42. foo4(4);
  43. cout << “foo4” <<endl;
        1. A& a = foo1(1);
  44. A& b = foo2(2);
  45. A& c = foo3(3);
  46. A& d = foo4(4);
  47. return 0;
  48. }
    1. 最后的运行结果是:

AA:1
foo1
AA:2
foo2
AA:3
AA:3
foo3
AA:4
foo4
AA:1
AA:3
AA:4
AA:3
AA:2

当然前面的内容:

AA:1
foo1
AA:2
foo2
AA:3
AA:3
foo3
AA:4
foo4

第二个函数与第三个函数可以很明显的看到效率的差异。因为foo3函数中析构函数出现了两次。

(这里第一和第四个函数有明显错误,可以根据后面的测试程序看出)

但是第一个函数也恰恰说明 return Integer(left.i+right.i); //创建一个临时对象并返回他,不会调用析构函数,效率高。
这句话有些问题。因为在调试的时候可以看出有调用析构函数。并且结果

AA:1
AA:3
AA:4
AA:3
AA:2

也能说明问题。

由于第一个函数和第四个函数产生的效果一样。

所以我提出一个可能的假设:

return Integer(left.i+right.i);
只有当返回值为Integer,而非Integer&才能有创建一个临时对象并返回他,不会调用析构函数。

当然因为程序的正确性要求,我们不可能编写类似于foo1的函数。

  1. int hoare_partition( int a[], int low, int high)
  2. {
  3. int x=a[low];
  4. int i=low-1;
  5. int j=high+1;
  6. while (1)
  7. {
  8. do {j–;}
  9. while (a[j]>x);
  10. do {i++;}
  11. while (a[i]<x);
  12. if (i<j)
  13. swap(a[i],a[j]);
  14. else return j;
  15. }
  16. }
    1. void hoare_quicksort( int a[], int low, int high)
  17. {
  18. int q;
  19. if (low<high)
  20. {
  21. q=hoare_partition(a,low,high);
  22. hoare_quicksort(a,low,q);
  23. hoare_quicksort(a,q+1,high);
  24. }
  25. }
      1. int _tmain( int argc, _TCHAR* argv[])
  26. {
  27. int a[9]={45,32,1,5,34,2,4,32,2};
  28. hoare_quicksort(a,0,8);
  29. for ( int i = 0; i< 9; i++)
  30. cout << a[i]<< " " ;
  31. return 0;
  32. }

这个树的定义的确很有问题。其实AVLTree和SplayTree以及RedBlackTree都是self-adjusting Tree

因为如果是树做索引那么大部分的时间将用来查找。这个树在查找上可以将查找的节点提升到树根,插入时也是一样。这样提高了查找的效率。并且操作系统有一种说法是近来用
到的,将来用到的几率也会很大(LRU原理)。删除,既然删除对于此树来说再也没有什么,那就直接删除算了。

根据这几点想法。自己做一个self-adjusting Tree。但是还没有验证是否能达到实际水平的O(nlogn)。虽然理论上这个树并不能达到这样一个时间
复杂度。但是对于实际数据来说,还是有可能达到的。不知道有没有这么lucky。

因为对于这个树来说插入和查找操作其实差不多。

所以下面只介绍插入操作。找到要插入的地方,反遍历单旋转(这里和SplayTree不同一点是只使用单旋转)

TreeNode* insertNode(TreeNode* subroot,TreeNode* prev,T& data)

返回值为当前子树根节点

1.subroot是否为空,创建新的节点,并返回subroot

2.如果不为空

A.subroot中的值 < data中的值,对subroot右子树调用insertNode(),subroot
与当前右子树根节点采用旋转操作。将两个节点位置对换。

B.subroot中的值 > data中的值,对subroot左子树调用insertNode(),subroot
与当前左子树根节点采用旋转操作。将两个节点位置对换。

C.subroot中的值 == data中的值,do nothing

3.查看该节点是否已成为根节点。如果是的话,调整根节点的值。

下面给出代码。

  1. template < class T>
  2. class SelfTree: public BinaryTree
  3. {
  4. private :
  5. // return the sub tree root
  6. //        a               b
  7. //       /       ->        /
  8. //      b                   a
  9. TreeNode* sLeftRotate(TreeNode* a,TreeNode* b)
  10. {
  11. a->setLeft(b->getRight());
  12. b->setRight(a);
  13. return b;
  14. }
      1. // return the sub tree root
  15. //        a               b
  16. //         /     ->      /
  17. //          b           a
  18. TreeNode* sRightRotate(TreeNode* a, TreeNode* b)
  19. {
  20. a->setRight(b->getLeft());
  21. b->setLeft(a);
  22. return b;
  23. }
        1. TreeNode* insertNode(TreeNode* subroot,TreeNode* prev,T& data)
  24. {
  25. if (subroot == NULL)
  26. {
  27. subroot = new TreeNode(data);
  28. return subroot;
  29. }
  30. else
  31. {
  32. TreeNode* tempNode = NULL;
  33. TreeNode* tempRoot = NULL;
  34. if (subroot->getData() > data)
  35. {
    1. tempNode = insertNode(subroot->getLeft(),subroot,data);
  36. tempRoot = sLeftRotate(subroot,tempNode);
    1. }
  37. else if (subroot->getData() < data)
  38. {
  39. tempNode = insertNode(subroot->getRight(),subroot,data);
  40. tempRoot = sRightRotate(subroot,tempNode);
  41. }
  42. else
  43. {
  44. throw “the same key” ;
  45. }
    1. if (prev == NULL)
  46. {
  47. this ->head = tempRoot;
  48. }
  49. else
  50. {
  51. if (prev->getData() > tempRoot->getData())
  52. {
  53. prev->setLeft(tempRoot);
  54. }
  55. else
  56. {
  57. prev->setRight(tempRoot);
  58. }
  59. }
  60. return tempRoot;
  61. }
  62. }
  63. public :
  64. SelfTree(T& data):BinaryTree(data)
  65. {
    1. }
    1. ~SelfTree()
  66. {
    1. }
    1. void insertNode(T& data)
  67. {
  68. insertNode( this ->head,NULL,data);
  69. }
    1. };
0%