- /*
- * Problem_1.cpp
- *
- * Created on: 2012-8-27
- * Author: Administrator
- */
- #include<stdio.h>
- struct BSTreeNode{
- int value;
- struct BSTreeNode *pLeft,*pRight;
- BSTreeNode(){
- pLeft=pRight=NULL;
- }
- };
- //创建链表用到的两个指针
- BSTreeNode *head=NULL,*tail=NULL;
- //只要调整输出的位置,就分别对应着三种不同的遍历方式
- void createList(BSTreeNode *cur){
- cur->pLeft=tail;//把当前的root接到链表的尾部
- if(tail!=NULL){//双向连接
- tail->pRight=cur;
- }else{
- head=cur;
- }
- tail=cur;//更新尾结点为当前结点,或者说:尾结点后移
- }
- BSTreeNode* visit(BSTreeNode *root){
- if(root!=NULL){
- // printf("%d ",root->value);//先序
- visit(root->pLeft);
- // printf("%d ",root->value);//中序
- createList(root);
- visit(root->pRight);
- // printf("%d ",root->value);//后序
- }
- return root;
- }
- void addNode(BSTreeNode **root,int value){
- BSTreeNode *p;
- if(NULL!=*root){
- if(value>(*root)->value){
- addNode(&((*root)->pRight),value);
- }else if(value<(*root)->value){
- addNode(&((*root)->pLeft),value);
- }else{
- printf("the node with value %d is in the tree!\n",value);
- }
- }else{
- p=new BSTreeNode();
- p->value=value;
- *root=p;
- }
- }
- int main(){
- BSTreeNode *root=NULL;
- int data[]={10,6,14,4,8,12,16};
- for(int i=0;i<7;i++){
- addNode(&root,data[i]);
- }
- visit(root);
- //output 其实只选择一种即可,如果选择tail,则是降序输出,选择head,则是升序输出
- while(tail!=NULL){
- printf("%d ",tail->value);
- tail=tail->pLeft;
- }
- prinft("\n");
- while(head!=NULL){
- printf("%d ",head->value);
- head=head->pRight;
- }
- return 0;
- }
分析:
1:由于要求链表是有序的,可以借助二叉树中序遍历,因为中序遍历算法的特点就是从小到大访问结点。当遍历访问到根结点时,假设根结点的左侧已经处理好,只需将根结点与上次访问的最近结点(左子树中最大值结点)的指针连接好即可。进而更新当前链表的最后一个结点指针。
2:由于中序遍历过程正好是转换成链表的过程,即可采用递归处理
转换代码如下:
- struct BinaryTreeNode
- {
- int m_nVlaue;
- BinaryTreeNode* m_pLeft;
- BinaryTreeNode* m_pRight;
- };
- /*
- 递归遍历中的转换过程
- 参数:处理当前结点,当前链表的最后一个结点(初始值为空)
- */
- void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)
- {
- if(pNode == NULL)
- return;
- BinaryTreeNode* pCurrent = pNode;
- //递归处理左子树
- if (pCurrent->m_pLeft != NULL)
- ConvertNode(pNode->m_pLeft,pLastNodeInList);
- //处理当前结点
- pCurrent->m_pLeft = *pLastNodeInList; //将当前结点的左指针指向已经转换好的链表的最后一个位置
- if (*pLastNodeInList!=NULL)
- *pLastNodeInList->m_pRight = pCurrent;//将已转换好的链表的最后一个结点的右指针指向当前结点
- *pLastNodeInList = pCurrent;//更新链表的最后一个结点
- //递归处理当前结点的右子树
- if (pCurrent->m_pRight != NULL)
- ConvertNode(pNode->m_pRight, pLastNodeInList);
- }
- BinaryTreeNode* Convert(BinaryTreeNode* pRootInTree)
- {
- BinaryTreeNode* pLastNodeInList = NULL;
- ConvertNode(pRootInTree, &pLastNodeInList);
- //pLastNodeInList指向双向链表的尾结点,再次遍历找到头结点
- BinaryTreeNode* pHeadOfList = pLastNodeInList;
- while(pHeadOfList != NULL && pHeadOfList->m_pLeft != NULL)
- pHeadOfList = pHeadOfList->m_pLeft;
- return pHeadOfList;
- }
测试代码如下:
创建一棵二叉排序树,可以调用http://blog.youkuaiyun.com/zhaojinjia/article/details/9314989方法生成。
- int _tmain(int argc, _TCHAR* argv[])
- {
- int preorder[] = {10,6,4,8,14,12,16};
- int inorder[] = {4,6,8,10,12,14,16};
- BinaryTreeNode* pRoot = Construct(preorder,inorder,7);
- BinaryTreeNode* pList = Convert(pRoot);
- while ( pList!=NULL )
- {
- cout << pList->m_nVlaue <<" ";
- pList = pList->m_pRight;
- }
- cout << endl;
- return 0;
- }
返回结果如下图所示: