zoukankan      html  css  js  c++  java
  • 把二元查找树转换成排序的双向链表

        题目:输入一颗二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整指针的指向。

    例如,将图1中的二叉搜索树转换成一个排序的双向链表:4=6=8=10=12=14=16。


    图1 二叉搜索树

        我们先来看一下这个题目该如何求解,然后再给出相应的源码。首先题目要求不能创造新的结点,那么,我们就只能使用树本身的结点,但是双向链表还有前驱和后继两个指针怎么办?答案是使用树的左孩子来做前驱指针,右孩子来做后继指针。又因为链表需要有序,所以使用中序遍历。

        解体思路:

        1)构造二叉查找树

        2)定义一个全局指针变量,指向双向链表的首元素。

        3)中序遍历二叉查找树,对于每次根节点的访问,修改其左孩子为链表的最后一个元素,修改其右孩子为NULL,那么这个元素的后继怎么办?由下一个元素来设置。

        具体代码如下:

    BSTree.h:

    #ifndef _BSTREE_H_
    #define _BSTREE_H_
    typedef struct _tagBSTreeNode
    {
        int m_nVal;
        _tagBSTreeNode * m_pLeft;
        _tagBSTreeNode * m_pRight;
    }BSTreeNode;
    extern BSTreeNode * pHead;
    //追加树结点
    int AppendNode(BSTreeNode **, int nNum);
    //打印树结点
    void PrintTree(BSTreeNode ** ppTree);
    //释放树
    void Clear(BSTreeNode ** ppTree);
    //转换为有序双链表
    void InOrderTree(BSTreeNode ** ppTree);
    //销毁链表
    void ClearList(BSTreeNode * pHead);
    //打印链表
    void PrintList(BSTreeNode * pHead);
    //打印路径
    void PrintPath(BSTreeNode * pHead, int nSum);
    #endif
    BSTree.cpp:

    #include <stdlib.h>
    #include <stdio.h>
    #include "BSTree.h"
    
    //追加树结点
    int AppendNode(BSTreeNode ** ppTree, int nNum)
    {
    	BSTreeNode * pNewNode = NULL;
    	if (!ppTree)
    		return 0;
    	if (*ppTree == NULL)
    	{
    		pNewNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
    		if (!pNewNode)
    			return 0;
    		pNewNode->m_nVal = nNum;
    		pNewNode->m_pLeft = NULL;
    		pNewNode->m_pRight = NULL;
    		*ppTree = pNewNode;
    		return 1;
    	}
    	if ((*ppTree)->m_nVal > nNum)
    	{
    		AppendNode(&((*ppTree)->m_pLeft), nNum);
    	}
    	else if ((*ppTree)->m_nVal < nNum)
    	{
    		AppendNode(&((*ppTree)->m_pRight), nNum);
    	}
    	else
    	{
    		printf("树结点已经存在.
    ");
    		return 0;
    	}
    	return 1;
    }
    //打印树结点
    void PrintTree(BSTreeNode ** ppTree)
    {
    	if (!ppTree)
    		return;
    	if (*ppTree == NULL)
    	{
    		return;
    	}
    	if ((*ppTree)->m_pLeft)
    		PrintTree(&((*ppTree)->m_pLeft));
    	if (*ppTree)
    		printf("%d", (*ppTree)->m_nVal);
    	if ((*ppTree)->m_pRight)
    		PrintTree(&((*ppTree)->m_pRight));
    }
    
    //释放树
    void Clear(BSTreeNode ** ppTree)
    {
    	BSTreeNode * pLeftTree = NULL;
    	BSTreeNode * pRightTree = NULL;
    	if (!ppTree)
    		return;
    	if (*ppTree == NULL)
    		return;
    	if ((*ppTree)->m_pLeft)
    	{
    		pLeftTree = (*ppTree)->m_pLeft;
    		Clear(&pLeftTree);
    	}
    	if ((*ppTree)->m_pRight)
    	{
    		pRightTree = (*ppTree)->m_pRight;
    		Clear(&pRightTree);
    	}
    	if (*ppTree)
    	{
    		free(*ppTree);
    		*ppTree = NULL;
    	}
    	return;
    }
    
    //以左孩子为前驱
    //以右孩子为后继
    BSTreeNode * pHead = NULL;
    
    void AppendNode2List(BSTreeNode * pInput)
    {
    	BSTreeNode * pCurNode = NULL;
    	if (pInput == NULL)
    		return;
    	if (!pHead)
    	{
    		pHead = pInput;
    		pInput->m_pLeft = NULL;
    		pInput->m_pRight = NULL;
    		return;
    	}
    	pCurNode = pHead;
    	while (pCurNode->m_pRight)
    	{
    		pCurNode = pCurNode->m_pRight;
    	}
    	pCurNode->m_pRight = pInput;
    	pInput->m_pLeft = pCurNode;
    	pInput->m_pRight = NULL;
    	return ;
    }
    
    //打印树结点
    void InOrderTree(BSTreeNode ** ppTree)
    {
    	if (!ppTree)
    		return;
    	if (*ppTree == NULL)
    	{
    		return;
    	}
    	if ((*ppTree)->m_pLeft)
    		InOrderTree(&((*ppTree)->m_pLeft));
    	if (*ppTree)
    		AppendNode2List(*ppTree);
    	if ((*ppTree)->m_pRight)
    		InOrderTree(&((*ppTree)->m_pRight));
    }
    
    void PrintList(BSTreeNode * pHead)
    {
    	BSTreeNode * pCurNode = NULL;
    	if (!pHead)
    		return;
    	pCurNode = pHead;
    	printf("
    链表数据:
    ");
    	while (pCurNode)
    	{
    		printf("%d	", pCurNode->m_nVal);
    		pCurNode = pCurNode->m_pRight;
    	}
    	return;
    }
    
    void ClearList(BSTreeNode * pHead)
    {
    	BSTreeNode * pCurNode = NULL;
    	if (!pHead)
    		return;
    	while (pHead)
    	{
    		pCurNode = pHead->m_pRight;
    		free(pHead);
    		pHead = pCurNode;
    	}
    	return;
    }
    main.cpp:

    //把二叉查找树转换为有序的双链表
    //要求不可以创建新结点,只可以改变指针
    //提示:
    //可以将左孩子用于指向前驱结点
    //可以将右孩子用于指向后继结点
    #define _CRTDBG_MAP_ALLOC
    #include <stdlib.h>
    #include <stdio.h>
    #include <crtdbg.h>
    #include "BSTree.h"
    
    void main()
    {
    	BSTreeNode * pTree = NULL;
    	if (AppendNode(&pTree, 5) == NULL)
    	{
    		printf("追加失败.
    ");
    		return;
    	}
    	if (AppendNode(&pTree, 4) == NULL)
    	{
    		printf("追加失败.
    ");
    		return;
    	}
    	if (AppendNode(&pTree, 3) == NULL)
    	{
    		printf("追加失败.
    ");
    		return;
    	}
    	if (AppendNode(&pTree, 2) == NULL)
    	{
    		printf("追加失败.
    ");
    		return;
    	}
    	if (AppendNode(&pTree, 1) == NULL)
    	{
    		printf("追加失败.
    ");
    		return;
    	}
    	PrintTree(&pTree);
    	InOrderTree(&pTree);
    	PrintList(pHead);
    	ClearList(pHead);
    	_CrtDumpMemoryLeaks();
    	system("pause");
    	return;
    }
    运行效果如图1所示:

    图1 运行效果

        图1是代码的运行效果,希望大家能够回去实践一下,加深体会。

       

  • 相关阅读:
    Java基础知识➣面向对象(八)
    Linux(CentOS7)安装Tomcat
    Java基础知识➣发送Emai和访问MySQL数据库(七)
    Java基础知识➣网络Socket(六)
    JS 的点点滴滴
    git 快速入门(二)
    zxing 生成二维码
    js生成二维码
    Markdown简介
    java常用string inputStream转换
  • 原文地址:https://www.cnblogs.com/new0801/p/6176984.html
Copyright © 2011-2022 走看看