记录线性表和二叉树常见的算法设计
定义结点
#define maxsize 20
// 定义链表结点
typedef struct lnode {
int data;
struct lnode* next;
} LNode;
//定义二叉树结点
typedef struct bnode {
int data;
struct bnode* lchild;
struct bnode *rchild;
} BNode;
建立链表和二叉树
//向BST内插入节点
void Insert(BNode *&bt, int x) {
if (!bt) {
bt = new BNode();
bt->data = x;
bt->lchild = bt->rchild = 0;
}
else if (bt->data > x) {
Insert(bt->lchild, x);
}
else {
Insert(bt->rchild, x);
}
}
// 建立BST
void CreateBtree(BNode *&bt, int nums[], int n) {
int i;
for (i = 0; i < n; i++) {
Insert(bt, nums[i]);
}
}
//建立链表,采用尾插法,头结点不存储数据
void CreateList(LNode*& l, int nums[], int n) {
int i;
LNode* p = l;
for (i = 0; i < n; i++) {
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = nums[i];
p->next = s;
s->next = NULL;
p = s;
}
}
判断两颗二叉树是否相同
bool Same(BNode* a, BNode* b) {
if (!a && !b) {
return 1;
}
else if (!a || !b || a->data != b->data) {
return 0;
}
else {
return Same(a->lchild, b->lchild)*Same(a->rchild, b->rchild);
}
}
交换二叉树的左右子树
void Switch(BNode*& bt) {
if (bt) {
//采用后序遍历思想
Switch(bt->lchild);
Switch(bt->rchild);
BNode* p = bt->lchild;
bt->lchild = bt->rchild;
bt->rchild = p;
}
}
合并两个(升序)有序单链表
void Merge(LNode*& pa, LNode*& pb) {
LNode* p = pa->next, * q = pb->next, * r = pa;
while (p && q) {
if (p->data > q->data) {
r->next = q;
r = q;
q = q->next;
}
else {
r->next = p;
r = p;
p = p->next;
}
}
//链接剩余部分
if (q) {
r->next = q;
}
if (p) {
r->next = p;
}
}
删除单链表中拥有相同值的多余结点
void Del_Same(LNode*& pa) {
//基本思路:一个工作指针p,两个负责删除的指针q,s
//对于p所指向的每个结点,q、s负责遍历后续的结点,查找是否存在相同的结点
LNode* p, * q, * s;
for (p = pa->next; p != 0; p = p->next) { //这里p!=0等价于p!=NULL
for (q = p->next, s = p; q != 0;) {
if (q->data == p->data) {
s->next = q->next;
free(q);
q = s->next;
}
else {
s = q;
q = q->next;
}
}
}
}
求结点x在树中的双亲结点
void parents(BNode* bt, int x) {
//基本思路:设置队列q,采用层次遍历思想
BNode* q[maxsize];
int r = 0, i, flag = 0;
BNode* p = bt;
while (p) {
if (p->data == x) {
flag = 1;
break;
}
else if(p->data > x) {
q[r++] = p;
p = p->lchild;
}
else {
q[r++] = p;
p = p->rchild;
}
}
if (flag) {
for (i = 0; i < r; i++) {
//这里需要对每个结点的左右孩子判空,否则无法输出
if ((q[i]->lchild && q[i]->lchild->data == x) || (q[i]->rchild && q[i]->rchild->data == x)) {
break;
}
}
if (i < r) {
printf("结点x的双亲结点为: %d\t", q[i]->data);
}
else{
printf("结点x无双亲节点\n");
}
}
else {
printf("该结点不存在\n");
}
}
求结点在二叉树中的层次
void Layer(BNode* bt, int x) {
//基本思路:队列+层次遍历思想
BNode* q[maxsize];
int r = -1, f = -1, level = 1, flag = 0;
q[++r] = bt;
while (r > f) {
BNode* p = q[++f];
if (p->data == x) {
flag = 1;
break;
}
else {
level++;
if (p->lchild) {
q[++r] = p->lchild;
}
if (p->rchild) {
q[++r] = p->rchild;
}
}
}
if (flag) {
printf("结点的层次为: %d\t", level);
}
else {
printf_s("不存在这样的结点\n");
}
}
链表上实现直接插入排序
void InsertSort(LNode*& head) {
//基本思路:设置工作指针p,负责指向无序部分的首结点,设置工作指针q,负责遍历有序部分查找合适的插入位置
LNode* p, * q;
int t;
if (head == 0 || head->next == 0) {
printf_s("链表为空");
return;
}
for (p = head->next; p != 0; p = p->next) {
for (q = head->next; q->next != p; q = q->next) {
if (q->data > p->data) {
t = q->data;
q->data = p->data;
p->data = t;
break;
}
}
}
}
统计二叉树的结点个数
//非递归
int Nodes(BNode* bt) {
int count = 0, r = -1, f = -1;
BNode* Q[maxsize];
BNode* p;
Q[++r] = bt;
while (f < r) {
p = Q[++f];
count++;
if (p->lchild) {
Q[++r] = p->lchild;
}
if (p->rchild) {
Q[++r] = p->rchild;
}
}
return count;
}
//递归
int Nodes_DG(BNode* bt) {
if (!bt) {
return 0;
}
return Nodes_DG(bt->lchild) + Nodes(bt->rchild) + 1;
}
求二叉树的高度
//非递归,借助队列实现
int Height(BNode* bt) {
int h = 0, r = -1, f = -1;
BNode* Q[maxsize];
BNode* p;
Q[++r] = bt;
while (f < r) {
p = Q[++f];
if (p->lchild) {
Q[++r] = p->lchild;
h++;
}
if (p->rchild) {
Q[++r] = p->rchild;
h++;
}
}
return h;
}
//递归
int Height_DG(BNode* bt) {
int lh, rh;
if (!bt) {
return 0;
}
lh = Height_DG(bt->lchild);
rh = Height_DG(bt->rchild);
return (lh > rh) ? lh + 1 : rh + 1;
}
求二叉树的WPL
int wpl = 0;
void WPL(BNode* bt, int depth) {
if (!bt->lchild&&!bt->rchild) {
wpl += (bt->data) * depth;
}
if (bt->lchild) {
WPL(bt->lchild, depth + 1);
}
if (bt->rchild) {
WPL(bt->rchild, depth + 1);
}
}
求叶子节点个数
int End_Nodes(BNode* bt) {
if (!bt) return 0;
if (!bt->lchild && !bt->rchild) return 1;
return End_Nodes(bt->lchild) + End_Nodes(bt->rchild);
}
求某一层结点的个数
int Level_Nodes(BNode* bt, int level) {
if (level <= 0 || !bt) {
return 0;
}
if (level <= 1) {
return 1;
}
return Level_Nodes(bt->lchild, level - 1) + Level_Nodes(bt->rchild, level - 1);
}