二叉樹和二叉排序樹的操作

二叉樹和二叉排序樹的操作

參考書籍-王道-書籍結構-代碼已在vs2019驗證過!

1.二叉樹的遍歷

二叉樹的建樹(層次建樹),前序、中序、後序遍歷、中序非遞歸遍歷、層次遍歷

#include <iostream>
typedef char BiElemType;
typedef struct BiTNode {
	BiElemType c;//c就是書籍上的data
	struct BiTNode* lchild;
	struct BiTNode* rchild;
}BiTNode, * BiTree;

typedef struct tag {
	BiTree p;
	struct tag* pnext;
}tag_t, * ptag_t;

//棧的相關數據結構
#define MaxSize 50
typedef BiTree ElemType;
typedef struct {
	ElemType data[MaxSize];
	int top;
}SqStack;
void InitStack(SqStack& S);
bool StackEmpty(SqStack& S);
bool Push(SqStack& S, ElemType x);
bool Pop(SqStack& S, ElemType& x);
bool GetTop(SqStack& S, ElemType& x);
//隊列的相關數據結構
typedef struct LinkNode {
	ElemType data;
	struct LinkNode* next;
}LinkNode;
typedef struct {
	LinkNode* front, * rear;
}LinkQueue;
void InitQueue(LinkQueue& Q);
bool IsEmpty(LinkQueue Q);
void EnQueue(LinkQueue& Q, ElemType x);
bool DeQueue(LinkQueue& Q, ElemType& x);
/******************遞歸實現****************************/
//前序遍歷=abdhiejcfg
void preOrder(BiTree p)
{
	if (p != NULL)
	{
		putchar(p->c);//等價於visit函數
		preOrder(p->lchild);
		preOrder(p->rchild);
	}
}
//中序遍歷  hdibjeafcg
void InOrder(BiTree p)
{
	if (p != NULL)
	{
		InOrder(p->lchild);
		putchar(p->c);
		InOrder(p->rchild);
	}
}
//後續遍歷hidjebfgca
void PostOrder(BiTree p)
{
	if (p != NULL)
	{
		PostOrder(p->lchild);
		PostOrder(p->rchild);
		putchar(p->c);
	}
}
/******************非遞歸實現*************************/
//中序遍歷非遞歸,非遞歸執行效率更高
void InOrder2(BiTree T)
{
	SqStack S;
	InitStack(S); BiTree p = T;
	while (p || !StackEmpty(S))//邏輯或||
	{
		if (p)
		{
			Push(S, p);
			p = p->lchild;
		}
		else {
			Pop(S, p); putchar(p->c);
			p = p->rchild;
		}
	}
}
//層次遍歷,廣度優先遍歷
void LevelOrder(BiTree T)
{
	LinkQueue Q;
	InitQueue(Q);
	BiTree p;
	EnQueue(Q, T);//樹根入隊
	while (!IsEmpty(Q))
	{
		DeQueue(Q, p);
		putchar(p->c);
		if (p->lchild != NULL)
			EnQueue(Q, p->lchild);
		if (p->rchild != NULL)
			EnQueue(Q, p->rchild);
	}
}
/******************層次建樹*************************/
//二叉樹的建樹(層次建樹)
BiTree InitTree()
{
	BiTree pnew;
	int i, j, pos;
	char c;
	BiTree tree = NULL;//樹根
	ptag_t phead = NULL, ptail = NULL, listpnew, pcur=NULL;
	//abcdefghij
	while (scanf_s("%c", &c) != EOF)
	{
		if (c == '\n')
		{
			break;
		}
		pnew = (BiTree)calloc(1, sizeof(BiTNode));//calloc申請空間並對空間進行初始化,賦值爲0
		pnew->c = c;
		listpnew = (ptag_t)calloc(1, sizeof(tag_t));
		listpnew->p = pnew;
		if (NULL == tree)
		{
			tree = pnew;//樹的根
			phead = listpnew;//鏈表頭
			ptail = listpnew;//鏈表尾
			pcur = listpnew;
			continue;
		}
		else {
			ptail->pnext = listpnew;//新結點放入鏈表,通過尾插法
			ptail = listpnew;
		}
		if (NULL == pcur->p->lchild)
		{
			pcur->p->lchild = pnew;
		}
		else if (NULL == pcur->p->rchild)
		{
			pcur->p->rchild = pnew;
			pcur = pcur->pnext;
		}
	}
	return tree;
}
// 二叉樹的建樹(層次建樹),前序、中序、後序遍歷、中序非遞歸遍歷、層次遍歷
int main(){
	BiTree tree=NULL;
	printf("輸入建樹:");
	tree=InitTree();
	printf("\n前序遍歷:");
	preOrder(tree);
	printf("\n中序遍歷:");
	InOrder(tree);
	printf("\n後序遍歷:");
	PostOrder(tree);
	printf("\n層次遍歷:");
	LevelOrder(tree);
	printf("\n中序遍歷非遞歸:");
	InOrder2(tree);
	printf("\n");
	system("pause");
}

2.二叉排序樹

二叉排序樹的遍歷和搜索

#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef struct BSTNode {
	KeyType key;
	struct BSTNode* lchild, * rchild;
}BSTNode, * BiTree;

int BST_Insert(BiTree& T, KeyType k)
{
	if (NULL == T)
	{
		T = (BiTree)malloc(sizeof(BSTNode));
		T->key = k;
		T->lchild = T->rchild = NULL;
		return 1;
	}
	else if (k == T->key)
		return 0;
	else if (k < T->key)
		return BST_Insert(T->lchild, k);
	else
		return BST_Insert(T->rchild, k);
}

void Creat_BST(BiTree& T, KeyType str[], int n)
{
	T = NULL;
	int i = 0;
	while (i < n)
	{
		BST_Insert(T, str[i]);
		i++;
	}
}
//遞歸算法簡單,但執行效率較低,實現留給大家編寫
BSTNode* BST_Search(BiTree T, KeyType key, BiTree& p)
{
	p = NULL;
	while (T != NULL && key != T->key)
	{
		p = T;
		if (key < T->key) T = T->lchild;
		else T = T->rchild;
	}
	return T;
}
//這個書上沒有
void DeleteNode(BiTree& root, KeyType x) {
	if (root == NULL) {
		return;
	}
	if (root->key > x) {
		DeleteNode(root->lchild, x);
	}
	else if (root->key < x) {
		DeleteNode(root->rchild, x);
	}
	else { //查找到了刪除節點
		if (root->lchild == NULL) { //左子樹爲空
			BiTree tempNode = root;
			root = root->rchild;
			free(tempNode);
		}
		else if (root->rchild == NULL) { //右子樹爲空
			BiTree tempNode = root;
			root = root->lchild;
			free(tempNode);
		}
		else {//左右子樹都不爲空
		   //一般的刪除策略是左子樹的最大數據 或 右子樹的最小數據 代替該節點(這裏採用查找左子樹最大數據來代替)
			BiTree tempNode = root->lchild;
			while (tempNode->rchild != NULL) {
				tempNode = tempNode->rchild;
			}
			root->key = tempNode->key;
			DeleteNode(root->lchild, tempNode->key);
		}
	}
}

void InOrder(BiTree T)
{
	if (T != NULL)
	{
		InOrder(T->lchild);
		printf("%3d", T->key);
		InOrder(T->rchild);
	}
}
int main()
{
	BiTree T;
	BiTree parent;
	BiTree search;
	KeyType str[] = { 54,20,66,41,28,79,58 };
	printf("\n創建二叉排序樹:");
	Creat_BST(T, str, 7);
	InOrder(T);
	printf("\n");
	search = BST_Search(T, 41, parent);
	if (search)
	{
		printf("找到對應結點,值=%d\n", search->key);
	}
	else {
		printf("未找到對應結點\n");
	}
	DeleteNode(T, 40);
	InOrder(T);
	printf("\n");
	system("pause");
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章