一个小算法题目
/* 根据数组创建二元查找树,再把二元查找树转变成排序的双向链表 要求不能创建任何新的结点,只调整指针的指向。 10 / \ 6 14 / \ / \ 4 8 12 16 转换成双向链表:4=6=8=10=12=14=16。 */
第一版程序写出来如下:
struct BSTreeNode *bstree2dlist(struct BSTreeNode *bt) { struct BSTreeNode *anchor = NULL; struct BSTreeNode *ret = bt; if(bt->m_pLeft != NULL) { if(bt->m_pLeft->m_pRight != NULL) { anchor = bt; anchor->m_pLeft = _max(bstree2dlist(bt->m_pLeft)); anchor->m_pLeft->m_pRight = anchor; ret = anchor; } else { bt->m_pLeft = _max(bstree2dlist(bt->m_pLeft)); bt->m_pLeft->m_pRight = bt; ret = bt; } } if(bt->m_pRight != NULL) { if(bt->m_pRight->m_pLeft != NULL) { anchor = bt; anchor->m_pRight = _min(bstree2dlist(bt->m_pRight)); anchor->m_pRight->m_pLeft = anchor; ret = anchor; } else { bt->m_pRight = _min(bstree2dlist(bt->m_pRight)); bt->m_pRight->m_pLeft = bt; ret = bt->m_pRight; } } return ret; }
其中_max和_min分别找到链表中的最大(最右)和最小(最左)元素。
第二版:
struct BSTreeNode *bstree2dlist(struct BSTreeNode *bt) { if(bt->m_pLeft != NULL) { bt->m_pLeft = bstree2dlist(bt->m_pLeft); while(bt->m_pLeft->m_pRight != NULL) bt->m_pLeft = bt->m_pLeft->m_pRight; bt->m_pLeft->m_pRight = bt; } if(bt->m_pRight != NULL) { bt->m_pRight = bstree2dlist(bt->m_pRight); while(bt->m_pRight->m_pLeft != NULL) bt->m_pRight = bt->m_pRight->m_pLeft; bt->m_pRight->m_pLeft = bt; } return bt; }
把anchor这个“想象中”特殊处理的结点去掉了,思维惯性影响,原来是背负着抱负写上去的。还把_max、_min方法直接放函数里面。
网上的版本:
void bstree2dlist(struct BSTreeNode *root) { static struct BSTreeNode *last = NULL; if(root) { bstree2dlist(root->m_pLeft); if(last) { last->m_pRight = root; root->m_pLeft = last; } last = root; bstree2dlist(root->m_pRight); } }
想了一些:
- 始终未掌握递归程序的写法,脑细胞不够用,一旦涉及嵌套,像看《盗梦空间》一样,晕头转向。
- 背负着心智抱负去做东西,自己的行为及受到了限制;把一些样板的东西放在那里,妄想通过它来找到某种捷径;最终,发现正是它在拖后腿。
- 凡事总是从薄->厚->“薄”。前者的薄是无知,后者的薄是深刻了解一件事物后剩下的骨干,排除自己烂熟的东西之后所“新”认识到的东西。
- K.C.K.T
- 效率!