一、数据结构定义
1、顺序二叉树
/* 顺序二叉树 */
typedef char TreeType;
typedef struct seqTree{
int MAXNUM; // 最大元素个数
int curNum; // 元素的个数
TreeType nodelist[]; // 顺序二叉树节点存储
} *SeqTree;
本次代码中二叉树的结构如下图,用层次序列可以表示为 ABCDEFG###H
2、链式栈
/* 链式栈 */
typedef char StackType;
typedef struct StackNode {
StackType data;
struct StackNode* next;
}StackNode;
typedef struct {
StackNode* top;
}LinkStack;
二叉树的非递归遍历(先序遍历、中序遍历、后续遍历)需要使用栈进行辅助
二、方法概览
1、二叉树
SeqTree CreateSeqTree(TreeType node[]); // 创建二叉树
int FindTreeNode(SeqTree T, char ch); // 查找指定结点的下标
char GetRoot(SeqTree T); // 求根结点的值
int GetParentIndex(SeqTree T, char ch); // 求指定结点的双亲结点的下标
int GetLeftChildIndex(SeqTree T, char ch); // 求指定结点的左孩子的下标
int GetRightChildIndex(SeqTree T, char ch); // 求指定结点的右孩子的下标
void LevelOrder(SeqTree T); // 层序遍历二叉树
void PreOrder(SeqTree T); // 先序遍历二叉树
2、栈
void InitStack(LinkStack* S);//初始化栈
int IsStackEmpty(LinkStack S);//判断栈是否为空
int PushStack(LinkStack* L, StackType data);//入栈
int PopStack(LinkStack* L, StackType* data);//出栈
int GetStackTop(LinkStack* L, StackType* x);//取栈顶元素
int DestroyStack(LinkStack* L);//销毁栈
三、方法详解
1、栈
//初始化栈
void InitStack(LinkStack* S) {
S->top = (StackNode*)malloc(sizeof(StackNode)); // 分配头节点
S->top = NULL; //初始化为空
}
//判断栈是否为空
int IsStackEmpty(LinkStack S) {
if (S.top == NULL) return 1;
else return 0;
}
//入栈
int PopStack(LinkStack* L, StackType* data) {
StackNode* del;
if (L->top == NULL) return -1;
else {
del = L->top;
*data = del->data;
L->top = L->top->next;
free(del);
return 0;
}
}
//出栈
int PushStack(LinkStack* L, StackType data) {
StackNode* news = (StackNode*)malloc(sizeof(struct StackNode));
if (news == NULL) return -1;
else {
news->data = data;
news->next = L->top;
L->top = news;
return 0;
}
}
//取栈顶元素
int GetStackTop(LinkStack* L, StackType* x) {
if (L->top == NULL) {
*x = NULL;
return -1;
}
else {
*x = L->top->data;
return 1;
}
}
//销毁栈
int DestroyStack(LinkStack* L) {
int cnt = 0;
if (L == NULL) return 0;
struct StackNode* p = L->top, * q;
free(L);
while (p->next != NULL) {
q = p->next;
cnt++;
free(p);
p = q;
}
return cnt;
}
2、二叉树基本操作
// 创建二叉树
SeqTree CreateSeqTree(TreeType node[]) {
SeqTree T = (SeqTree)malloc(sizeof(struct seqTree));
for (T->curNum = 0; T->curNum < strlen(node); T->curNum++)
T->nodelist[T->curNum] = node[T->curNum];
return T;
}
// 查找指定结点的下标
int FindTreeNode(SeqTree T, char ch) {
for (int i = 0; i < T->curNum; i++)
if (T->nodelist[i] == ch)
return i;
return -1;
}
// 求根结点的值
char GetRoot(SeqTree T){
// 若二叉树为空,则返回#
if (T->curNum == 0) return '#';
return(T->nodelist[0]);
}
// 求指定结点的双亲结点的下标
int GetParentIndex(SeqTree T, char ch){
int i, p;
// 返回双亲结点的下标
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若双亲不存在,则返回-1
if (p <= 0 || p >= T->curNum || T->nodelist[(p - 1) / 2] == 32) return -1;
return (p - 1) / 2;
}
// 求指定结点的左孩子的下标
int GetLeftChildIndex(SeqTree T, char ch){
int i, p;
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若左孩子不存在,则返回-1
if (p < 0 || p >= T->curNum || T->nodelist[2 * p + 1] == 32)
return -1;
return 2 * p + 1;
}
// 求指定结点的右孩子的下标
int GetRightChildIndex(SeqTree T, char ch){
int i, p;
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若左孩子不存在,则返回-1
if (p < 0 || p >= T->curNum || T->nodelist[2 * (p + 1)] == 32)
return -1;
return 2 * (p + 1);
}
3、二叉树递归遍历
(1)层次遍历
// 层序遍历二叉树
void LevelOrder(SeqTree T){
for (int i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == '#');
else printf("%c ", T->nodelist[i]);
}
}
(2)先序遍历
// 先序遍历二叉树
void PreOrder(SeqTree T){
char c;
LinkStack s;
InitStack(&s);
PushStack(&s, T->nodelist[0]);
while (!IsStackEmpty(s)) {
GetStackTop(&s, &c);
PopStack(&s, &c);
if (FindTreeNode(T, c) != -1) {
if (c == '#');
else printf("%c ", c);
PushStack(&s, T->nodelist[GetRightChildIndex(T, c)]);
PushStack(&s, T->nodelist[GetLeftChildIndex(T, c)]);
}
}
}
四、运行结果
main方法代码如下:
int main(void) {
TreeType node[15] = { 'A','B','C','D','E','F','G','#','#','#','H'};
SeqTree T = CreateSeqTree(node);
printf("根结点的值: %c", GetRoot(T));
printf("\n结点A双亲的下标: %d", GetLeftChildIndex(T, 'A'));
printf("\n结点A左孩子的下标: %d", GetRightChildIndex(T, 'A'));
printf("\n结点A右孩子的下标: %d", GetParentIndex(T, 'A'));
printf("\n层序遍历结果:");
LevelOrder(T);
printf("\n先序遍历结果:");
PreOrder(T);
}
运行结果如下:
五、源代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/* 顺序二叉树 */
typedef char TreeType;
typedef struct seqTree{
int MAXNUM; // 最大元素个数
int curNum; // 元素的个数
TreeType nodelist[]; // 顺序二叉树节点存储
} *SeqTree;
/* 链式栈 */
typedef char StackType;
typedef struct StackNode {
StackType data;
struct StackNode* next;
}StackNode;
typedef struct {
StackNode* top;
}LinkStack;
void InitStack(LinkStack* S);//初始化栈
int IsStackEmpty(LinkStack S);//判断栈是否为空
int PushStack(LinkStack* L, StackType data);//入栈
int PopStack(LinkStack* L, StackType* data);//出栈
int GetStackTop(LinkStack* L, StackType* x);//取栈顶元素
int DestroyStack(LinkStack* L);//销毁栈
SeqTree CreateSeqTree(TreeType node[]); // 创建二叉树
int FindTreeNode(SeqTree T, char ch); // 查找指定结点的下标
char GetRoot(SeqTree T); // 求根结点的值
int GetParentIndex(SeqTree T, char ch); // 求指定结点的双亲结点的下标
int GetLeftChildIndex(SeqTree T, char ch); // 求指定结点的左孩子的下标
int GetRightChildIndex(SeqTree T, char ch); // 求指定结点的右孩子的下标
void LevelOrder(SeqTree T); // 层序遍历二叉树
void PreOrder(SeqTree T); // 先序遍历二叉树
/*------------- 栈基本操作 ---------------*/
//初始化栈
void InitStack(LinkStack* S) {
S->top = (StackNode*)malloc(sizeof(StackNode)); // 分配头节点
S->top = NULL; //初始化为空
}
//判断栈是否为空
int IsStackEmpty(LinkStack S) {
if (S.top == NULL) return 1;
else return 0;
}
//入栈
int PopStack(LinkStack* L, StackType* data) {
StackNode* del;
if (L->top == NULL) return -1;
else {
del = L->top;
*data = del->data;
L->top = L->top->next;
free(del);
return 0;
}
}
//出栈
int PushStack(LinkStack* L, StackType data) {
StackNode* news = (StackNode*)malloc(sizeof(struct StackNode));
if (news == NULL) return -1;
else {
news->data = data;
news->next = L->top;
L->top = news;
return 0;
}
}
//取栈顶元素
int GetStackTop(LinkStack* L, StackType* x) {
if (L->top == NULL) {
*x = NULL;
return -1;
}
else {
*x = L->top->data;
return 1;
}
}
//销毁栈
int DestroyStack(LinkStack* L) {
int cnt = 0;
if (L == NULL) return 0;
struct StackNode* p = L->top, * q;
free(L);
while (p->next != NULL) {
q = p->next;
cnt++;
free(p);
p = q;
}
return cnt;
}
/*------------- 树基本操作 ---------------*/
// 创建二叉树
SeqTree CreateSeqTree(TreeType node[]) {
SeqTree T = (SeqTree)malloc(sizeof(struct seqTree));
for (T->curNum = 0; T->curNum < strlen(node); T->curNum++)
T->nodelist[T->curNum] = node[T->curNum];
return T;
}
// 查找指定结点的下标
int FindTreeNode(SeqTree T, char ch) {
for (int i = 0; i < T->curNum; i++)
if (T->nodelist[i] == ch)
return i;
return -1;
}
// 求根结点的值
char GetRoot(SeqTree T){
// 若二叉树为空,则返回#
if (T->curNum == 0) return '#';
return(T->nodelist[0]);
}
// 求指定结点的双亲结点的下标
int GetParentIndex(SeqTree T, char ch){
int i, p;
// 返回双亲结点的下标
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若双亲不存在,则返回-1
if (p <= 0 || p >= T->curNum || T->nodelist[(p - 1) / 2] == 32) return -1;
return (p - 1) / 2;
}
// 求指定结点的左孩子的下标
int GetLeftChildIndex(SeqTree T, char ch){
int i, p;
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若左孩子不存在,则返回-1
if (p < 0 || p >= T->curNum || T->nodelist[2 * p + 1] == 32)
return -1;
return 2 * p + 1;
}
// 求指定结点的右孩子的下标
int GetRightChildIndex(SeqTree T, char ch){
int i, p;
for (i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == ch) p = i;
}
// 若左孩子不存在,则返回-1
if (p < 0 || p >= T->curNum || T->nodelist[2 * (p + 1)] == 32)
return -1;
return 2 * (p + 1);
}
// 层序遍历二叉树
void LevelOrder(SeqTree T){
for (int i = 0; i < T->curNum; i++) {
if (T->nodelist[i] == '#');
else printf("%c ", T->nodelist[i]);
}
}
// 先序遍历二叉树
void PreOrder(SeqTree T){
char c;
LinkStack s;
InitStack(&s);
PushStack(&s, T->nodelist[0]);
while (!IsStackEmpty(s)) {
GetStackTop(&s, &c);
PopStack(&s, &c);
if (FindTreeNode(T, c) != -1) {
if (c == '#');
else printf("%c ", c);
PushStack(&s, T->nodelist[GetRightChildIndex(T, c)]);
PushStack(&s, T->nodelist[GetLeftChildIndex(T, c)]);
}
}
}
int main(void) {
TreeType node[15] = { 'A','B','C','D','E','F','G','#','#','#','H'};
SeqTree T = CreateSeqTree(node);
printf("根结点的值: %c", GetRoot(T));
printf("\n结点A双亲的下标: %d", GetLeftChildIndex(T, 'A'));
printf("\n结点A左孩子的下标: %d", GetRightChildIndex(T, 'A'));
printf("\n结点A右孩子的下标: %d", GetParentIndex(T, 'A'));
printf("\n层序遍历结果:");
LevelOrder(T);
printf("\n先序遍历结果:");
PreOrder(T);
}