欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构之树(C语言实现)

程序员文章站 2022-03-23 09:19:06
...
enum Status{ERROR = 0,OK = 1};

//二叉树
//--------------------------------------------------------------------------------
//二叉树的链式存储

//第一种结构
typedef struct BinaryNode BinaryNode,*BinaryTree;
struct BinaryNode{
	GenericPointer pData;
	BinaryNode* pLeft;
	BinaryNode* pRight;
}
//第二种结构(添加双亲指针)
typedef struct BinaryNode BinaryNode,*BinaryTree;
struct BinaryNode{
	GenericPointer pData;
	BinaryNode* pLeft;
	BinaryNode* pRight;
	BinaryNode* pParent;
}

//--------------------------------------------------------------------------------
//二叉树的遍历

//前序遍历
Status TraverseInPreorder(BinaryTree pRoot,Status(*visit)()){
	if(pRoot == NULL){
		return OK;
	}
	else{
		if(visit(pRoot->pData)==ERROR){
			return ERROR;
		}
		TraverseInPreorder(pRoot->pLeft,visit);
		TraverseInPreorder(pRoot->pRight,visit);
	}
	return OK;
}
//中序遍历
Status TraverseInOrder(BinaryTree pRoot,Status(*visit)()){
	if(pRoot == NULL){
		return OK;
	}
	else{
		TraverseInOrder(pRoot->pLeft,visit);
		if(visit(pRoot->pData)==ERROR){
			return ERROR;
		}
		TraverseInOrder(pRoot->pRight,visit);
	}
	return OK;
}
//后序遍历
Status TraverseInPostOrder(BinaryTree pRoot,Status(*visit)()){
	if(pRoot == NULL){
		return OK;
	}
	else{
		TraverseInPostOrder(pRoot->pLeft,visit);
		TraverseInPostOrder(pRoot->pRight,visit);
		if(visit(pRoot->pData)==ERROR){
			return ERROR;
		}
	}
	return OK;
}

//--------------------------------------------------------------------------------
//统计叶子结点的个数
//方法一:利用遍历算法完成,代码略
//方法二:采用分治算法,空树返回0,只有一个结点返回1,否则返回左右子树的叶子结点数之和
int NumOfLeaves(BinaryTree pRoot){
	if(pRoot == NULL) return 0;
	if(pRoot->pLeft == NULL && pRoot->pRight == NULL) return 1;
	return NumOfLeaves(pRoot->pLeft)+NumOfLeaves(pRoot->pRight);
}

//--------------------------------------------------------------------------------
//利用拓展的先序序列创建二叉树
//拓展的先序序列:在先序序列的基础上,用特定元素表示空子树
//e.g.  AB.DF..G..C.E.H..
void CreateBinaryTree(BinaryTree *pRoot){//注意这里是一个二重指针
	char ch;
	ch = getchar();
	if(ch == '.') *pRoot = NULL;
	else{
		*pRoot = (BinaryTree)malloc(sizeof(BinaryTree));
		*pRoot -> data = ch;//这里使用的是普通的二叉树结构
		CreateBinaryTree(&((*pRoot)->pLeft));
		CreateBinaryTree(&((*pRoot)->pRight));
	}
}

//还是利用先序序列创建二叉树
Status CreateBinaryTree(BinaryTree* pBinaryTree,char* preorderSequence){
	static int i=0;
	char rootData;
	BinaryNode* pRoot;
	rootData = preorderSequence[i++];
	if(rootData == '\0' || rootData == EMPTY_BINARY_NODE){
		*pBinaryTree=NULL;
        return OK;
	}
	pRoot=(BinaryNode*)malloc(sizeof(BinaryNode));
	if(pRoot == NULL)	return ERROR;
	pRoot->data=rootData;
	*pBinaryTree=pRoot;
	if(CreateBinaryTree(&(pRoot->pLeft),preorderSequence)==ERROR){
        return ERROR;
    }
	if(CreateBinaryTree(&(pRoot->pRight),preorderSequence)==ERROR){
        return ERROR;
    }
    return OK;
}

	
//--------------------------------------------------------------------------------
//求二叉树的高度
int DepthOfBinaryTree(BinaryTree pRoot){
	int h1,h2;
	if(pRoot == NULL) return 0;
	else{
		h1 = DepthOfBinaryTree(pRoot->pLeft)+1;
		h2 = DepthOfBinaryTree(pRoot->pRight)+1;
		return  h1 > h2 ? h1 : h2;
}

//--------------------------------------------------------------------------------
//线索二叉树
typedef enum {NO_CHILD=0, CHILD=1} ThreadTag;
typedef struct BinaryNode BinaryNode, *BinaryTree;
struct BinaryNode {
    GenericPointer pData;
    ThreadTag leftTag;
    BinaryNode* pLeft;
    ThreadTag rightTag;
    BinaryNode* pRight;
};
//按中序进行线索化
void ThreadBinaryTree(BinaryTree pRoot){
	static BinaryNode* pPre = NULL;
	if(pRoot == NULL) return;
	ThreadBinaryTree(pRoot->pLeft);//线索化左子树
	//加线索
	if(pRoot -> leftTag == NO_CHILD){
		pRoot -> pLeft = pPre;
	}
	if(pPre != NULL && pPre -> rightTag == NO_CHILD){
		pPre -> pRight = pRoot;
	}
	pPre = pRoot;
	
	ThreadBinaryTree(pRoot->pRight);//线索化右子树
}

//找中序线索树的前驱节点
BinaryNode* PreviousInorderNode(BinaryNode* pNode){
	BinaryNode* pTemp;
	if(pNode -> leftTag == NO_CHILD)	return pNode->pLeft;
	pTemp = pNode->pLeft;
	//找左子树中最右下端的结点
	while(pTemp->rightTag==CHILD){
		pTemp=pTemp->pRight; 
	}
	return pTemp;
}

//找中序线索树的后继节点
BinaryNode* NextInorderNode(BinaryNode* pNode){
	BinaryNode* pTemp;
	if(pNode->rightTag==NO_CHILD)	return pNode->pRight;
	pTemp=pNode->pRight; 
	//找右子树最左下端的节点
	while(pTemp->leftTag==CHILD){
        pTemp=pTemp->pLeft; 
    }
	return pTemp;
}

//遍历中序线索树
//在中序线索树上找第一个结点
BinaryNode* FirstInorderNode(BinaryTree pRoot){
	if(pRoot == NULL)	return NULL;
	BinaryNode* pTemp = pRoot;
	//找左子树中最左的结点
	while(pTemp->leftTag==CHILD){
		pTemp = pTemp -> pLeft;
	}
	return pTemp;
}
//遍历
Status TraverseInorderThreadedBinaryTree(BinaryTree pRoot,Status(*visit)()){
	BinaryNode* pTemp = FirstInorderNode(pRoot);
	while(pTemp != NULL){
		if(visit(pTemp) == ERROR){
			return ERROR;
		}
		pTemp = NextInorderNode(pTemp);
	}
		return OK;
}


//--------------------------------------------------------------------------------
//利用序列组合创建二叉树
//利用先序和中序序列创建二叉树
Status CreateBinaryTree(BinaryTree* pBinaryTree,char* preorder,char* inorder,int n){
	if(n <= 0) {
        *pBinaryTree=NULL;
        return OK;
    }
	BinaryNode* pRoot = (BinaryNode*)malloc(sizeof(BinaryNode));
	if(pRoot == NULL)	return ERROR;
	pRoot->data = preorder[0];
    *pBinaryTree = pRoot;
	int i=Locate(inorder, preorder[0],n); //返回根的中序位置,该函数省略
	if (i < 0)	return ERROR;
	if(CreateBinaryTree(&(pRoot->pLeft),preorder+1,inorder,i)==ERROR){
        return ERROR;
    }
	if(CreateBinaryTree(&(pRoot->pRight),preorder+i+1,inorder+i+1,n-i-1)==ERROR){
        return ERROR;
    } 
    return OK;
}

//--------------------------------------------------------------------------------
//树
//--------------------------------------------------------------------------------
//双亲表示法
typedef struct {
    TreeElem data;
    int parent;
} TreeNode;
typedef struct {
    TreeNode Tree[MAX_TREE_SIZE];
    int numOfNodes;
} Tree;

//孩子表示法
typedef struct ChildNode{//孩子链表结点定义
    int  child;
    struct ChildNode *pNext;
} ChildNode;
typedef struct {//顺序表结点的定义
    TreeElem data;
    ChildNode* pFirstChild;
} TreeNode;
typedef struct {
    TreeNode  nodeArray[MAX_TREE_SIZE];
    int root;//根节点在线性表中的位置
    int numOfNodes;
} Tree;

//孩子兄弟表示法
typedef struct TreeNode{
    TreeElem data;
    struct TreeNode *pFirstChild;
    struct TreeNode *pNextSibling;
} TreeNode, *Tree;


//树的先根遍历(采用孩子兄弟表示法)
//一:
Status RootFirst(Tree root,Status(*visit)()){
	TreeNode* pTemp;
	if(root != NULL){
		if(visit(root->data) == ERROR)	return ERROR;
		pTemp = root -> pFirstChild;
		while(p != NULL){
			RootFirst(p);
			p = p -> pNextSibling;
		}
	}
	return OK;
}

//二:
Status RootFirst(Tree root,Status(*visit)()){
	if(root != NULL){
		if(visit(root->data) == ERROR)	return ERROR;
		RootFirst(root->data);
		RootFirst(root->pNextSibling);
	}
	return OK;
}


//--------------------------------------------------------------------------------
//哈夫曼树
//--------------------------------------------------------------------------------
//类型定义
typedef struct {
    int weight;
    int parent;
    int leftChild;
    int rightChild;
} HuffmanNode,*HuffmanTree;

//哈夫曼树的构建
HuffmanTree ConstructHuffmanTree(int weight[],int n){
	int m = 2*n-1;
	HuffmanTree ht = (HuffmanTree)malloc(m*sizeof(HuffmanNode));
	if(ht == NULL)	return NULL;
	//初始化
	int i;
	for(i = 0;i < n;i++){
		ht[i].weight = weight[i];
		ht[i].parent = -1;
		ht[i].leftChild = -1;
		ht[i].rightChild = -1;
	}
	for(i = n;i < m;i++){
		ht[i].weight = 0;
		ht[i].parent = -1;
		ht[i].leftChild = -1;
		ht[i].rightChild = -1;
	}
	//构建
	int a,b;//存放权值最小的两个结点并使权值a<b
	for(i = n;i < m;i++){
		if(Select(hf,i,&a,&b)==ERROR)	return NULL;
		ht[i].weight = ht[a].weight+ht[b].weight;
		ht[a].parent = i;
		ht[b].parent = i;
		ht[i].leftChild = a;
		ht[i].rightChild = b;
	}
	return ht;
}

Status Select(HuffmanTree ht,int n,int* pa,int* pb){
	int i,t,a,b;
	for(i = 0;i < n;i++){//找无双亲的第一个结点
		if(ht[i].parent < 0)	break;
	}
	if(i >= n)	return ERROR;
	a = i;
	for(i = a+1;i < n;i++){//找无双亲的第二个结点
		if(ht[i].parent < 0)	break;
	}
	if(i >= n)	return ERROR;
	b = i;
	if(ht[b].weight < ht[a].weight){
		t = a;
		a = b;
		b = t;
	}
	i = a > b ? a : b;
	for(i=i+1;i < n;i++){
		if(ht[i].parent<0 && ht[i].weight<ht[b].weight){
			b = i;
			if(ht[b].weight<ht[a].weight){
				t = a;
				a = b;
				b = t;
			}
		}
	}
	*pa = a;
	*pb = b;
	return OK;
}

//哈夫曼编码
Status PrintHuffmanCode(HuffmanTree ht,int numOfLeaves){
	int i,j,p,k;
	char reverseCode[MAX_CODE_LENGTH];
	if(ht == NULL || numOfLeaves < 2){
		print("ERROR");
		return ERROR;
	}
	for(i = 0;i < numOfLeaves;i++){
		j = i;//从叶子到跟,倒着为第i个叶子编码
		k = 0;//数组的下标
		while(ht[j].parent>0){
			p = ht[j].parent;
			if(j == ht[p].leftChild){
				reverseCode[k] = '0';
			}
			else{
				reverseCode[k] = '1';
			}
			k++;
			j = p;
		}
		print("第%d个叶子节点的编码:");
		k = k-1;
		while(k >= 0){//倒序输出
			putchar(reverseCode[k]);
			k--;
		}
	}
	return OK;
}