数据结构学习(八)

二叉树的存储方式分为顺序存储和链式存储方式

顺序存储方式只能存储完全二叉树,也可以通过将普通二叉树补全转换为完全二叉树来存储

 

二叉树的链式存储方式

结点由三部分构成,左孩子,右孩子,值

typedef struct bitree
{
	int val;
	struct bitree* leftchild;
	struct bitree* rightchild;
};

初始化

bitree* inittree()
{
	bitree* bt = (bitree*)malloc(sizeof(bitree));
	bt->val = 1;

	bitree* bt2 = (bitree*)malloc(sizeof(bitree));
	bt2->val = 2;
	bitree* bt3 = (bitree*)malloc(sizeof(bitree));
	bt3->val = 3;
	bt->leftchild = bt2;
	bt->rightchild = bt3;

	bitree* bt4 = (bitree*)malloc(sizeof(bitree));
	bt4->val = 4;
	bitree* bt5 = (bitree*)malloc(sizeof(bitree));
	bt5->val = 5;
	bt2->leftchild = bt4;
	bt2->rightchild = bt5;
	bt4->leftchild = NULL;
	bt4->rightchild = NULL;
	bt5->leftchild = NULL;
	bt5->rightchild = NULL;

	bitree* bt6 = (bitree*)malloc(sizeof(bitree));
	bt6->val = 6;
	bitree* bt7 = (bitree*)malloc(sizeof(bitree));
	bt7->val = 7;
	bt3->leftchild = bt6;
	bt3->rightchild = bt7;
	bt6->leftchild = NULL;
	bt6->rightchild = NULL;
	bt7->leftchild = NULL;
	bt7->rightchild = NULL;

	return bt;
}

先序遍历

void printnode(bitree* bt)
{
	cout << bt->val << " ";
}

void frontbl(bitree* bt)
{
	if (bt == NULL)
	{
		return;
	}
	printnode(bt);
	frontbl(bt->leftchild);
	frontbl(bt->rightchild);
}


中序遍历

void middlebl(bitree* bt)
{
	if (bt == NULL)
	{
		return;
	}
	middlebl(bt->leftchild);
	printnode(bt);
	middlebl(bt->rightchild);
}


后序遍历

void lastbl(bitree* bt)
{
	if (bt == NULL)
	{
		return;
	}
	lastbl(bt->leftchild);
	lastbl(bt->rightchild);
	printnode(bt);
}


层次遍历

void ccbl1(bitree* bt1, bitree* bt2)
{
	if (bt1 == NULL || bt2 == NULL)
	{
		return;
	}
	printnode(bt1);
	printnode(bt2);
	ccbl1(bt1->leftchild, bt1->rightchild);
	ccbl1(bt2->leftchild, bt2->rightchild);
}

void ccbl(bitree* bt)
{
	printnode(bt);
	ccbl1(bt->leftchild, bt->rightchild);
}

线索二叉树

typedef struct xsbitree
{
	struct xsbitree* leftchild;
	struct xsbitree* rightchild;
	int val;
	int ltag;
	int rtag;
};

通过中序遍历构建线索二叉树

void middle(xsbitree* p,xsbitree* pre)
{
	if (p == NULL)
	{
		return;
	}
	middle(p->leftchild, pre);
	if (p->leftchild == NULL)
	{
		p->leftchild = pre;
		p->ltag = 1;
	}
	if (pre->leftchild != NULL && pre->rightchild == NULL)
	{
		pre->rightchild = p;
		pre->rtag = 1;
	}
	pre = p;
	middle(p->rightchild, pre);

}

void mxstree(xsbitree* bt)
{
	xsbitree* pre = NULL;
	middle(bt, pre);
	pre->rightchild = NULL;
	pre->rtag = 1;
}

普通二叉树三种表示方法

双亲表示法

#define max_size 100
typedef struct pnode
{
	int val;
	int parent;
};
typedef struct ptree
{
	pnode* node[max_size];
	int num;
};

初始化

ptree* initptree()
{
	ptree* pt = (ptree*)malloc(sizeof(ptree));
	pt->num = 7;

	pt->node[0] = (pnode*)malloc(sizeof(pnode));
	pt->node[0]->val = 0;
	pt->node[0]->parent = -1;

	pt->node[1] = (pnode*)malloc(sizeof(pnode));
	pt->node[1]->val = 1;
	pt->node[1]->parent = 0;

	pt->node[2] = (pnode*)malloc(sizeof(pnode));
	pt->node[2]->val = 2;
	pt->node[2]->parent = 0;

	pt->node[3] = (pnode*)malloc(sizeof(pnode));
	pt->node[3]->val = 3;
	pt->node[3]->parent = 0;

	pt->node[4] = (pnode*)malloc(sizeof(pnode));
	pt->node[4]->val = 4;
	pt->node[4]->parent = 2;

	pt->node[5] = (pnode*)malloc(sizeof(pnode));
	pt->node[5]->val = 5;
	pt->node[5]->parent = 2;

	pt->node[6] = (pnode*)malloc(sizeof(pnode));
	pt->node[6]->val = 6;
	pt->node[6]->parent = 3;

	return pt;
}

查找元素

void findnode(ptree* pt, int val)
{
	for (int i = 0; i < pt->num; i++)
	{
		if (val == pt->node[i]->val)
		{
			cout << "父节点:" << pt->node[pt->node[i]->parent]->val << "存储下标" << pt->node[i]->parent << endl;
		}
	}
}

孩子节点法

//孩子结点表示法
typedef struct cnode
{
	int loc;
	struct cnode* child;
};
typedef struct chead
{
	int val;
	cnode* chead;
};
typedef struct ctree
{
	chead* head[max_size];
	int num;
};

初始化

ctree* initctree()
{
	ctree* c = (ctree*)malloc(sizeof(ctree));

	c->head[0] = (chead*)malloc(sizeof(chead));
	c->head[0]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[0]->val = 0;
	cnode* c1 = (cnode*)malloc(sizeof(cnode));
	c1->loc = 1;
	c->head[0]->chead = c1;
	cnode* c2 = (cnode*)malloc(sizeof(cnode));
	c2->loc = 2;
	c1->child = c2;
	cnode* c3 = (cnode*)malloc(sizeof(cnode));
	c3->loc = 3;
	c3->child = NULL;
	c2->child = c3;

	c->head[1] = (chead*)malloc(sizeof(chead));
	c->head[1]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[1]->val = 1;
	cnode* c4 = (cnode*)malloc(sizeof(cnode));
	c4->loc = 4;
	c->head[1]->chead = c4;
	cnode* c5 = (cnode*)malloc(sizeof(cnode));
	c5->loc = 5;
	c4->child = c5;
	c5->child = NULL;

	c->head[2] = (chead*)malloc(sizeof(chead));
	c->head[2]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[2]->chead->child = NULL;
	c->head[2]->val = 2;

	c->head[3] = (chead*)malloc(sizeof(chead));
	c->head[3]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[3]->chead->child = NULL;
	c->head[3]->val = 3;

	c->head[4] = (chead*)malloc(sizeof(chead));
	c->head[4]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[4]->chead->child = NULL;
	c->head[4]->val = 4;

	c->head[5] = (chead*)malloc(sizeof(chead));
	c->head[5]->chead = (cnode*)malloc(sizeof(cnode));
	c->head[5]->chead->child = NULL;
	c->head[5]->val = 5;
	
	return c;
}

孩子兄弟表示法

将普通树转换为二叉树的表示方法

typedef struct cbtree
{
	cbtree* child;
	cbtree* brother;
	int val;
};

将普通树转换为二叉树

cbtree* bl(int val, cbtree* cb)
{
	if (!cb) return NULL;
	if (val == cb->val) return cb;
	return bl(val,cb->child) != NULL ? bl(val,cb->child) : bl(val,cb->brother);
}

cbtree* changtobitree(ptree* p)
{
	cbtree* cb = (cbtree*)malloc(sizeof(cbtree));
	cb->val = p->node[0]->val;
	cb->brother = NULL;
	cb->child = NULL;

	for (int i = 1; i < p->num; i++)
	{
		cbtree* temp = cb;
		cbtree* cb1 = (cbtree*)malloc(sizeof(cbtree));
		cb1->val = p->node[i]->val;
		cb1->brother = NULL;
		cb1->child = NULL;

		temp = bl(p->node[i]->parent, temp);
		//cout << temp->val << endl;
		if (temp->child == NULL)
		{
			temp->child = cb1;
		}
		else
		{
			temp = temp->child;
			while (temp->brother != NULL)
			{
				temp = temp->brother;
			}
			temp->brother = cb1;
		}
	}


	return cb;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值