将二叉查找树转换成有序的双向链表
题目
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。
分析
二叉查找树有一个性质:
一个节点的左子树上所有节点的值均小于该节点的值,并且在图上观看就是左子树上有最大值的节点在最右侧
一个节点的右子树上的所有节点的值均大于该节点的值,并且在图上观看就是右子树上有最小值的节点在最左侧
用递归的思想,将一个节点A的左右子树分别变成双向链表,返回左子树的最大值节点Aleft和右子树的最小值节点Aright,最后将A、Aleft和Aright的指针连接起来。
代码
/* author:SwordStraw http://onestraw.net */ #include<stdio.h> #include<stdlib.h> //搜索二叉树节点 typedef struct BSTreeNode{ int cargo; BSTreeNode *left; BSTreeNode *right; }BSTreeNode; //深度优先建树,假定该树的所有节点值均为正数, 输入负数和0表示回上一层父结点 BSTreeNode* createBSTree(int high) { BSTreeNode *root; root = NULL; int value; printf("第%d层, 请输入节点的值: ", high); scanf("%d", &value); if(value > 0) { root = (BSTreeNode*)malloc(sizeof(BSTreeNode)); root->cargo = value; root->left = createBSTree(high+1); root->right = createBSTree(high+1); } return root; } //返回二叉树的最右侧节点 BSTreeNode *rightOfTree(BSTreeNode *root) { BSTreeNode *p; p = root; while(p && p->right) p = p->right; return p; } //返回二叉树的最左侧节点 BSTreeNode *leftOfTree(BSTreeNode *root) { BSTreeNode *p; p = root; while(p && p->left) p = p->left; return p; } //把二叉搜索树转换成双向链表 //left指针指向驱节点,right指针指向后继节点 void ConvertToDulLinkList(BSTreeNode *cur) { BSTreeNode *lchild, *rchild; lchild = rchild = NULL; if(cur->left) { ConvertToDulLinkList(cur->left); lchild = rightOfTree(cur->left);//左子树最大的 } if(cur->right) { ConvertToDulLinkList(cur->right); rchild = leftOfTree(cur->right);//右子树最小的 } if(lchild) { lchild->right= cur; cur->left=lchild; } if(rchild) { rchild->left=cur; cur->right=rchild; } } //遍历双向链表 //direction表示方向,0表示从后向前,1表示从前向后 void traverseTree(BSTreeNode *head, int direction) { while(head) { printf("%d->",head->cargo); if(direction == 1) head = head->right; else if(direction == 0) head = head->left; } printf("\n"); } //测试程序 int main(int argc, char *argv[]) { printf("[深度优先建树, 假定该树的所有节点值均为正数, 输入负数和0表示回上一层父结点]\n"); BSTreeNode *root; /*构造如下一棵二叉搜索树 10 / \ 6 14 / \ / \ 4 8 12 16 如果嫌输入麻烦,可直接将下面粘贴到命令行:10 6 4 0 0 8 0 0 14 12 0 0 16 0 0 */ root = createBSTree(0); BSTreeNode *head, *tail;//链表的头和尾 head = leftOfTree(root); tail = rightOfTree(root); ConvertToDulLinkList(root); printf("\n双向遍历\n"); traverseTree(head,1); traverseTree(tail,0); return 0; }
留下评论