需求
输入一棵二叉搜索树,将该二叉树转换成一个排序的双向链表,
(要求:不能创建任何新的节点只能调整树中指针的指向)
例如:
转换成双向链表后:
线索
在二叉搜索树中,左子树的值总是比根节点,右子树的值总是大于根节点,因此我们在将二叉搜索树变换成双向链表时,原先指向左子节点的指针调整为链表中指向前一个节点的指针,原先指向右子节点的指针调整为指向后一个节点的指针。
为了记录已经调整好的链表,需要一个指向链表尾节点的指针。
只有二叉树的中序遍历是有序的,所以解决本题必须要用到二叉树的中序遍历。
实现
void convertTreeCore(BTNode *pNode, BTNode **pLastInList){
if (!pNode){
//数据非法,
return;
}
BTNode *pc = pNode;
if (pNode->left){
convertTreeCore(pNode->left,pLastInList);
}
pc->left = *pLastInList;//将之前的链表挂到当前的二叉树节点
if (*pLastInList){//说明当前的链表不是空链表,将当前二叉树节点挂到双向链表的后面
(*pLastInList)->right = pc;
}
*pLastInList = pc;//双向链表的尾指针后移,指向当前链表的尾节点
if (pNode->right){
convertTreeCore(pNode->right, pLastInList);
}
}
BTNode* convertTree(BTNode *root){
BTNode *pLastInList = NULL;
convertTreeCore(root, &pLastInList);
//执行完上面函数,pLastInList指向当前链表的尾节点
BTNode *head = pLastInList;
while (head != NULL&&head->left){//判断head是否为空的目的是想判断传入的元素第否合法
head = head->left;
}
return head;
}
调试代码:
//定义二叉树的节点
typedef struct node{
int data;
struct node *left;
struct node *right;
}BTNode;
//创建二叉搜索树
BTNode* creatBinSortTree(int data[], int len){
BTNode *root = NULL, *p = NULL, *pa = NULL, *c = NULL;
for (int i = 0; i < len; i++){
//为新的节点分配单元
p = (BTNode*)malloc(sizeof(BTNode));
p->data = data[i];
p->left = p->right = NULL;
if (!root){
root = p;
}
else{
c = root;
while (c){
pa = c;
if (c->data < p->data){
c = c->right;
}
else{
c = c->left;
}
}
if (pa->data < p->data){
pa->right = p;
}
else{
pa->left = p;
}
}
}
return root;
}
//中序遍历二叉树
void inOrder(BTNode *root){
if (root){
inOrder(root->left);
printf("%d ", root->data);
inOrder(root->right);
}
}
//打印双向链表
void printLink(BTNode *head){
for (BTNode *p = head; p; p = p->right){
printf("%d ",p->data);
}
}
//主函数
int main(void){
int data[8] = { 3, 2, 5, 8, 4, 7, 6, 9 };
BTNode *root = creatBinSortTree(data, 8);
//中序遍历二叉树
inOrder(root);
printf("\n");
BTNode *head = convertTree(root);
//打印双向链表
printLink(head);
system("pause");
return 0;
}
调试结果:
思考:
能否将一个双向链表调整成二叉搜索树?
答:我认为不能,因为无法确定该二叉树的根节点是哪个元素。