算法题1:二元查找树转换成有序双向链表
来源:互联网 发布:linux for 循环判断 编辑:程序博客网 时间:2024/06/13 13:26
在CSDN上发现一个很不错的算法博客:http://blog.csdn.net/v_JULY_v。博客主人无私地整理了各大公司面试的算法题,在此非常感谢。今天,整整一天,才完成了第一个算法题,可见我的专业基础多么地薄弱。革命尚未成功,同志需要继续努力。
现将一天的劳动成功发表于此,以示鼓励。
题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ /
6 14
/ / / /
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
首先我们定义的二元查找树 节点的数据结构如下:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};
算法思想:
找到有序双向链表中节点的左右指针节点在二元查找树中的位置
对应关系如下:
有序双向链表中节点的左指针:二元查找树中对应节点的左子树中最大节点
有序双向链表中节点的右指针:二元查找树中对应节点的右子树中最小节点
程序实现:
1)按照先序遍历方式遍历二元查找树,
2)遍历的同时根据上述算法思想更新节点的左右指针,
3)为了得到双向链表,根据以下关系:
p->m_pLeft = q ==》 q->m_pRight = p;
p->m_pRight = q ==》 q->m_pLeft = p;
补齐指针。
4)二元查找树遍历结束时,最终形成一个双向链表。
程序源码:
tree.h
/********************************tree.h : 定义树的头文件********************************/#ifndef __TREE_H__#define __TREE_H__typedef int ElemType;struct BSTreeNode{ElemType m_nValue;struct BSTreeNode *m_pLeft;struct BSTreeNode *m_pRight;};typedef struct BSTreeNode *pBSTreeNode;typedef struct BSTreeNode *pSearchTree;pSearchTree Insert(ElemType x,pSearchTree T);void InOrderTree(pSearchTree T);void PrintList(pBSTreeNode pHead);void TreeToList(pSearchTree pT);pBSTreeNode GetListHead(pSearchTree pRoot);#endif
tree.c
#include <stdio.h>#include <stdlib.h>#include "tree.h"int counter = 0; //统计节点遍历的次数// 打印双向链表void PrintList(pBSTreeNode pHead){if (NULL == pHead){return;}printf("\n%11s: ","List");pBSTreeNode p = pHead;do {printf("%d, ", p->m_nValue);p = p->m_pRight;}while(p != NULL);printf("\n");}/*创建新节点*/pBSTreeNode NewNode(ElemType x){pBSTreeNode new_node;new_node = (pBSTreeNode)malloc(sizeof(struct BSTreeNode)); if ( NULL == new_node){ printf("malloc error\n"); return NULL; }else{ new_node->m_nValue = x; new_node->m_pLeft = new_node->m_pRight = NULL; }return new_node;}/*在二叉树中插入节点*/pSearchTree Insert(ElemType x, pSearchTree T){if (NULL == T){T = NewNode(x); //创建新节点}else {if ( x < T->m_nValue){ //如果新插入的节点小于当前节点,则插入其左节点T->m_pLeft = Insert(x, T->m_pLeft); } else{if ( x > T->m_nValue){T->m_pRight = Insert(x, T->m_pRight);//如果大于当前节点,则插入其右节点}else{printf("%d is already exsited\n",x); //不允许重复节点}}}return T;}/*中序遍历二叉树*/void InOrderTree(pSearchTree T){if (NULL != T){InOrderTree(T->m_pLeft);printf("%d, ", T->m_nValue);InOrderTree(T->m_pRight);}}/********************************************** 查找节点在双向链表中的左指针节点: 二元查找树中该节点左子树中最大的节点*********************************************/ pBSTreeNode FindLeft(pSearchTree pT){pBSTreeNode p;if (NULL == pT){return NULL;}if ( NULL == pT->m_pRight){ //如果当前节点不存在右节点,则当前节点就是所找节点return pT;}else{p = FindLeft(pT->m_pRight);}return p;}/****************************************** 查找节点在双向链表中对应的右指针节点: 二元查找树中该节点右子树中最小的节点*******************************************/pBSTreeNode FindRight(pSearchTree pT){pBSTreeNode p;if (NULL == pT){return NULL;} if (NULL == pT->m_pLeft){ //如果当前节点不存在左节点,则当前节点即为所找节点return pT;}else{ p = FindRight(pT->m_pLeft); }return p;}/**********************************************以先序遍历的方式遍历二元查找树,遍历的同时更新树中节点的左右指针,最终得到一个有序双向链表***********************************************/void TreeToList(pSearchTree pT){pSearchTree L,R;if (NULL == pT)return ;counter++;L = pT->m_pLeft; //先保存当前节点的左右子树R = pT->m_pRight;pT->m_pLeft = FindLeft(L); //查找当前节点在双向链表中的左指针节点pT->m_pRight = FindRight(R); //查找当前节点在双向链表中的右指针节点 TreeToList(L);TreeToList(R); if (pT->m_pLeft){ pT->m_pLeft->m_pRight = pT; //根据左指针,补齐对应的右指针 } if (pT->m_pRight){ pT->m_pRight->m_pLeft = pT; //根据右指针,补齐对应的左指针 }return ;}/****************************************从根节点开始,按照左指针的指向依次查找,一直找到双向链表的头结点为止。函数返回双向链表的头结点*****************************************/pBSTreeNode GetListHead(pBSTreeNode pT){if (NULL == pT) { return NULL; } pBSTreeNode p = pT;while(NULL != p->m_pLeft)p = p->m_pLeft;return p;}
main.c
#include <stdio.h>#include <stdlib.h>#include "tree.h"extern int counter;int main(){FILE *fp;int c;pSearchTree T;pBSTreeNode phead; //生成的双向链表的头结点T = NULL;fp = fopen("in.txt","r");if (NULL == fp){printf("open file in.txt failed\n");exit(0);}while (fscanf(fp,"%d",&c) != EOF ){T = Insert(c,T);}fclose(fp); printf("InOrderTree: ");InOrderTree(T);printf("\n");TreeToList(T); /*二元查找树转换为两个单向链表*/phead=GetListHead(T); /*得到双向链表的头指针*/PrintList(phead); /*打印输出双向链表*/printf("counter = %d\n",counter);return 0;}
测试数据in.txt
100 34 98 102 83 2 39 93 32 45 21 35 193 10 6 394 24 95 298 84 18 9 86 12 3 20 11 23 92 89
测试结果:
InOrderTree: 2, 3, 6, 9, 10, 11, 12, 18, 20, 21, 23, 24, 32, 34, 35, 39, 45, 83, 84, 86, 89, 92, 93, 95, 98, 100, 102, 193, 298, 394,
List: 2, 3, 6, 9, 10, 11, 12, 18, 20, 21, 23, 24, 32, 34, 35, 39, 45, 83, 84, 86, 89, 92, 93, 95, 98, 100, 102, 193, 298, 394,
counter = 30
- 算法题1:二元查找树转换成有序双向链表
- 【算法题】二元查找树转换成排序的双向链表
- 二元查找树转有序双向链表
- 二元查找树转有序的双向链表
- 算法面试题01:将一棵二元查找树转换成一个排序的双向链表
- 每天学习一算法系列(2)(把二元查找树转变成排序的双向链表,要求输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.)
- 第10题 把二元查找树转换成排序的双向链表
- 1将该二元查找树转换成一个排序的双向链表
- 微软等面试100题筛选答案-1-二元查找树转换成一个排序的双向链表
- (三)二元查找树转换双向链表
- 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表
- 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表
- 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
- [微软面试100题] 二元查找数变成有序的双向链表
- 树(1)把二叉查找树转换成有序的双向链表
- 把二元查找树转换成排序的双向链表
- 二元查找树转换成一个排序的双向链表
- 二元查找树转换成一个排序的双向链表
- Array.Copy(array1, array2, 2);
- js中继承的几种用法apply,call,prototype
- awk 实例练习(一)
- [sicily online]1048. Inverso
- awk 实例练习(二)
- 算法题1:二元查找树转换成有序双向链表
- windows7上帝模式
- Ubuntu 12.10方便操作套件
- QTP11.5发布,改名UFT
- 通过反射计算方法执行时间 包括out参数
- 通用Makefile
- 【木头Cocos2d-x 021】一个堆和栈引起的分手事件
- Linux系统下安装arm-linux-gcc 交叉编译器
- 在SharePoint Designer高级搜索页面中创建并暴露托管属性