二叉树,约瑟夫,多项式合并!

2015.2.9
星期一 晴

树的基本概念:

度数:一个节点的子树的个数为该节点的度数,一颗数的度数是指该树中节点的最大度数
树叶或者终端节点:度数为0的节点
高度或者深度:节点的层数等于父节点的层数加1,根节点的层数定义为1,树中节点层数最大值称为该树的高度或者深度
有序树:若树中每个节点的各子树的排列为从左到右,不能交换,即兄弟之间是有序的,则称该树为有序树
满二叉树:深度为K时有2^k-1个节点的二叉树
完全二叉树:只有最下面两层就度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。

对于完全二叉树有以下特点: 设节点数为n,某节点编号为i

数组实现:如果有N个节点需要N+1个数组空间,把数组0的位置空出来,从1开始排列,利用下面的公式计算每个i节点子节点的下标:
左子节点:2*i,右子节点:2*i+1;

满足:2*i<=n时,i子节点存在左孩子,且编号为2*i
满足:2*i+1<=n时,i子节点存在左孩子,且编号为2*i

用链表和递归函数实现一个树的创建:中间有很多打印的程序,方便看过程。
#include <stdio.h>
#include <stdlib.h>

typedef char bt_data_t;

typedef struct tree_node_t{
bt_data_t data;
struct tree_node_t *lchild,*rchild;
}bitree_t;

bitree_t *Create_Bitree(int i, bt_data_t a[],int n);

static int indent = 0;
static int step = 0;

int main()
{
bt_data_t bt_array[] = {0,‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘,‘g‘,‘h‘,‘i‘,‘j‘};
bt_data_t bt_array[] = {0,‘a‘,‘b‘,‘c‘,0,0,0,0,‘h‘,‘i‘,‘j‘}; //将数组改成非完全二叉树,补0

bitree_t *root;
printf("Begin creating B-tree ... \n");

root = Create_Bitree(1,bt_array,sizeof(bt_array)/sizeof(bt_data_t) - 1); //从根节点开始,调用递归函数创建二叉树的所有节点并插入数据
printf("Finished!\n");

return 0;
}

bitree_t *Create_Bitree(int i,bt_data_t a [],int n) //递归函数的创建
{
bitree_t *root;
int j;

printf("-------------->step<%2d>\n",step++);

indent++;

root = (bitree_t *)malloc(sizeof(bitree_t));
root->data = a[i]; //将数据写入结构体
printf("%d*cRoot(%c)\n",indent,‘-‘,root->data);

j = 2*i;
if(j <= n) //对于非完全而二叉树这样修改:if(j <= n && a[j] != ‘0‘) //判断是否存在左子树
{
printf("%*cRoot(%d)->Left(%d)\n",indent,‘-‘,i,j);
root->lchild = Create_Bitree(j, a, n);
}
else
{
printf("%*cRoot(%d)->Left(NULL)\n",indent,‘-‘,i);
root->lchild = NULL; //不存在左子树,怎返回NULL
}

j = 2*i+1;
if(j <= n) //对于非完全而二叉树这样修改:if(j <= n && a[j] != ‘0‘) //判断是否存在右子树
{
printf("%*cRoot(%d)->Right(%d)\n",indent,‘-‘,i,j);
root->rchild = Create_Bitree(j, a, n);
}
else
{
printf("%*cRoot(%d)->Right(NULL)\n",indent,‘-‘,i);
root->rchild = NULL;
}

indent--;

printf("<--------------step<%2d>\n",step++);

return root;
}

执行效果:

[email protected]:/mnt/hgfs/source test/pdf$ gcc bt_create1.c
[email protected]:/mnt/hgfs/source test/pdf$ ./a.out
Begin creating B-tree ...
-------------->step< 0>
1*cRoot(-)
-Root(1)->Left(2)
-------------->step< 1>
2*cRoot(-)
-Root(2)->Left(4)
-------------->step< 2>
3*cRoot(-)
-Root(4)->Left(8)
-------------->step< 3>
4*cRoot(-)
-Root(8)->Left(NULL)
-Root(8)->Right(NULL)
<--------------step< 4>
-Root(4)->Right(9)
-------------->step< 5>
4*cRoot(-)
-Root(9)->Left(NULL)
-Root(9)->Right(NULL)
<--------------step< 6>
<--------------step< 7>
-Root(2)->Right(5)
-------------->step< 8>
3*cRoot(-)
-Root(5)->Left(10)
-------------->step< 9>
4*cRoot(-)
-Root(10)->Left(NULL)
-Root(10)->Right(NULL)
<--------------step<10>
-Root(5)->Right(NULL)
<--------------step<11>
<--------------step<12>
-Root(1)->Right(3)
-------------->step<13>
2*cRoot(-)
-Root(3)->Left(6)
-------------->step<14>
3*cRoot(-)
-Root(6)->Left(NULL)
-Root(6)->Right(NULL)
<--------------step<15>
-Root(3)->Right(7)
-------------->step<16>
3*cRoot(-)
-Root(7)->Left(NULL)
-Root(7)->Right(NULL)
<--------------step<17>
<--------------step<18>
<--------------step<19>
Finished!

用函数指针可以给已经写好的函数增加额外的功能!!!!!!!!!!!

将数组data_t array[] = {0,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘0‘,‘F‘,‘0‘,‘0‘,‘G‘,‘H‘,‘0‘,‘0‘,‘I‘};中的字符插入数的相应位置,
并按照不同的遍历顺序打印出来:依次先序,中序,后序;

#include <stdio.h>
#include <stdlib.h>

typedef int data_t;

typedef struct tree{
data_t data;
struct tree *lchild;
struct tree *rchild;
}bitree_t;

bitree_t *Create_Bitree(int i,data_t a[],int n);
void Pre_Order(bitree_t *bt);
void In_Order(bitree_t *bt);
void Post_Order(bitree_t *bt);

main()
{
data_t array[] = {0,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘0‘,‘F‘,‘0‘,‘0‘,‘G‘,‘H‘,‘0‘,‘0‘,‘I‘};
bitree_t *root;
int len;

len = sizeof(array)/sizeof(data_t) - 1;
printf("begain create b-tree....\n");

root = Create_Bitree(1,array,len);

printf("finish\n");

printf("Pre_Order = ");
Pre_Order(root);
putchar(‘\n‘);
printf("In_Order = ");
In_Order(root);
putchar(‘\n‘);
printf("Post_Order = ");
Post_Order(root);
putchar(‘\n‘);

}

bitree_t *Create_Bitree(int i,data_t a[],int n) //建立树的程序和上面的程序一样
{
bitree_t *root;
int j;

root = (bitree_t *)malloc(sizeof(bitree_t));
if(root == NULL)
{
return NULL;
}

root->data = a[i];

j = 2 * i;
if((j <= n) && a[j] != ‘0‘)
{
root->lchild = Create_Bitree(j,a,n); //递归创建
}
else
{
root->lchild = NULL;
}

j = 2 * i + 1;
if((j <= n) && a[j] != ‘0‘)
{
root->rchild = Create_Bitree(j,a,n); //递归创建
}
else
{
root->rchild = NULL;
}

return root;
}

void Pre_Order(bitree_t *bt) //先序遍历二叉树,并打印出找到的数据
{
if(bt == NULL)
{
return ;
}
printf("%3c",bt->data); //根节点
Pre_Order(bt->lchild); //左子树
Pre_Order(bt->rchild); //右子树

//return ;
}

void In_Order(bitree_t *bt) //中序遍历二叉树,并打印出找到的数据
{
if(bt == NULL)
{
return ;
}
In_Order(bt->lchild); //左子树
printf("%3c",bt->data);//根节点
In_Order(bt->rchild); //右子树
}

void Post_Order(bitree_t *bt) //先序遍历二叉树,并打印出找到的数据
{
if(bt == NULL)
{
return ;
}
Post_Order(bt->lchild); //左子树
Post_Order(bt->rchild); //右子树
printf("%3c",bt->data); //根节点

}

执行效果:

[email protected]:/mnt/hgfs/source test/pdf$ gcc testtree.c
[email protected]:/mnt/hgfs/source test/pdf$ ./a.out
begain create b-tree....
finish
Pre_Order = A B D E G H C F I
In_Order = D B G E H A C I F
Post_Order = D G H E B I F C A
[email protected]:/mnt/hgfs/source test/pdf$

约瑟夫问题的链表的实现:
#include <stdio.h>
#include <stdlib.h>

void joseph(int n, int k, int m) //总共n个人,从第k个人的下一个开始作为1,数到m的人出局
{
int i;
linklist_t p,L,r;
L = NULL;

for(i = 1; i <= n; i++) //建立循环链表
{
p = (linklist_t)malloc(sizeof(linknode_t));
p->data = i;
if(L == NULL)
{
L = p;
}
else
{
r->next = p;
}
r = p;
}

for(i = 1; i < k; i++) //找到第一个开始计数的位置
{
r = r->next;
}
while(r->next != r) //人数大于1
{
for(i = 1; i <= m-2; i++) //这里是一个技巧性很强的操作,巧妙地利用已有的指针释放出局的数据,避免了利用额外的指针来做标记动作
{
r = r->next;
}
p = r->next;
r->next = p->next;
printf("%d",p->data);
free(p);
r = r->next;
}
printf("%d\n",r->data);

}

多项式的表示和相加:这里的操作很很特别,用两个结构体组成一个完整的多项式的表示,包括多项式的系数,指数,和指向下一个节点的指针

#include <stdio.h>
#include <stdlib.h>

typedef struct{ //这个结构体中包括了多项式的系数,指数
float coaf;
int exp;
}data_t;

typedef struct node{ //第二个结构体包括了第一个结构体和一个指向下个节点的指针
data_t data;
struct node *next;
}linknode_t;*linklist_t;

void Addpoly(linklist_t pa,linklist_t pb) //这个函数时多项式的所有项进项操作,包括从小到大的排序和合并的过程,一次性全部完成。
{
linklist_t pre,u;
float sum;

pre = pa;
pa = pa->next;

u = pb;
pb = pb->next;

free(u);

while(pa && pb)
{
if(pa->data.exp < pb->data.exp) //将小的多项式放在结构体的前面
{
pre->next = pa;
pre = pa;
pa = pa->next;
}

if(pa->data.exp > pb->data.exp)
{
pre->next = pb;
pre = pb;
pb = pb->next;
}
else
{
sum = pa->data.coaf + pb->data.coaf; //合并多项式的系数
if(sum != 0.0)
{
pa->data.coaf = sum;
pre->next = pa;
pre = pa;
pa = pa->next;
}
else
{
u = pa; //当节点合并后的系数为0后,删除相应的节点pa
pa = pa->next;
free(u);
}

u = pb; //删除相应的节点pa
pb = pb->next;
free(u);
}

}
if(pa != NULL) //当其中一个节点遍历完毕后,将还有数据的链表直接放到合并后的链表的后面
{
pre->next = pa;
}
else
{
pre->next = pb;
}
}

***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************
***************************************************************************************************************************************************************

时间: 2024-10-10 22:59:49

二叉树,约瑟夫,多项式合并!的相关文章

C算法与数据结构-线性表的应用,多项式求和---ShinePans

/*---上机作业作业,二项式加法---*/ /*---By 潘尚 ---*/ /*---日期: 2014-5-8 . ---*/ /*---题目:---*/ //假设有两个稀疏多项式A和B,设计算法完成下列任务 //1.输入并建立多项式A和B; //2.求两个多项式的和多项式C; //3.求两个多项式的积多项式D; //输出4个多项式A,B,C,D; #include <stdio.h> #include <stdlib.h> #include <string.h>

命题作文:在一棵IPv4地址树中彻底理解IP路由表的各种查找过程

这是一篇命题作文.近期一直想写点东西,但一直找不到题目.正好收到一封邮件,有人问我Linux路由表的布局问题以及路由缓存的问题,加之前些日子又帮人做了一个片上路由表,所以认为这是个好题目,索性花了多半个周末的时间,奋笔疾书. 前面的套话 不写命题作文已经11年了.最后一次是在高考的考场上. 收到邮件时,被人要求写这样的命题作文,其实我是拒绝的,由于你不能叫我写我就立即去写,首先我自己得懂这个.我又不能说到了写完了的时候贴了非常多baidu出来的图片,说了非常多套话,人家一看就知道我这是转载或者翻

ACM数论之旅13---母函数(又叫生成函数)(痛并快乐着(╭ ̄3 ̄)╭)

(前排出售零食瓜子) 前言:(????不看会吃亏的) 接下来要讲的算法比较难,一般人听不懂,因为你不能用常人的思想去理解 就像高数(说多了都是泪( >﹏<.)) 你要用常规方法去想肯定很累( ̄▽ ̄)~* 有时候一直半解的多读几遍反而高效 就像矩阵,发明矩阵的人是天才,我们只能在使用矩阵的同时一直感叹:“哇!好神奇!这样也可以!” 而不是先研究为什么他会有这么多神奇的性质 因为,毕竟从发明者角度来说,他就是考虑了这么多才创造出了神奇的矩阵 而如果矩阵的每一个性质你都一点点研究过去,终有一天,你也

MATLAB实现牛顿插值

牛顿插值法的原理,在维基百科上不太全面,具体可以参考这篇文章.同样贴出,楼主作为初学者认为好理解的代码. function p=Newton1(x1,y,x2) %p为多项式估计出的插值 syms x n = length(x1); %差商的求法 for i=2:n f1(i,1)=(y(i)-y(i-1))/(x1(i)-x1(i-1)); end for i=2:n for j=i+1:n f1(j,i)=(f1(j,i-1)-f1(j-1,i-1))/(x1(j)-x1(j-i)); en

C语言范例学习03-下

树与图 3.5 二叉树及其应用 PS:二叉树是最经典的树形结构,适合计算机处理,具有存储方便和操作灵活等特点,而且任何树都可以转换成二叉树. 实例101 二叉树的递归创建 实例102 二叉树的遍历 问题:编程实现递归创建二叉树,要求显示树的节点内容,深度及叶子节点数. 构造一棵二叉树,分别采用先序遍历.中序遍历和后序遍历遍历该二叉树. 逻辑:二叉树是一棵由一个根节点(root)和两棵互不相交的分别称作根的左子树和右子树所组成的非空树,左子树和右子树有同样都是一棵二叉树. 存储二叉树通常采用二叉链

霍夫曼树 二三树 红黑树 B树 B+树

霍夫曼树: 特点:带权路径长度最短,∑(每个节点的权重)*(每个节点的层数) 生成:每次合并权值最小的两个节点(子树)建立二叉树,将合并后的子树作为新节点,权值为节点(子树)权值之和 二三树: 特点:平衡查找树,每个叶子节点为空且层数相同,查找时间复杂度O(lgn) 生成:2节点包含一个key和两个子节点(left->key<key<right->key),3节点包含两个key和三个子节点(left->key<key1<middle->key<key2

母函数及其应用+模板

部分摘自这位大佬的博客https://www.cnblogs.com/linyujun/p/5207730.html 生成函数即母函数,是组合数学中尤其是计数方面的一个重要理论和工具. 最早提出母函数的人是法国数学家LaplaceP.S.在其1812年出版的<概率的分析理论>中明确提出“生成函数的计算”. 生成函数的应用简单来说在于研究未知(通项)数列规律,用这种方法在给出递推式的情况下求出数列的通项. 在这里我们不去高深地研究数学上母函数,而是讲讲简单的母函数应用. 1.母函数引入 就是把一

课设心得

课设心得 选题 最开始的时候是想选择图书管理系统的,因为有经验,但是不清楚为什么学委和我说已经被选满了,那个时候我应该是第一个选的,基本不可能被选满.于是我选择了多项式合并. 做题 与三重链表相比的难度 相较于三重链表而言,这道题可以做的非常简单,也可以做的与三重链表的复杂程度相仿.三重链表那个课设的难点在于组织三重链表的思路,以及对于三重链表的操作,前者更难一些,因为对其操作基本只是遍历(我帮助大约5--8个人设计了构造以及存数三重链表的函数.所以我认为我还是有一定发言权的).对于多项式合并,

(java描述)关于链表的代码-----单双、循环链表、约瑟夫环、多项式相加

将链表头尾倒置 将几个链表合并成一个新的链表,将链表中重复的节点去掉,并按大小排序 双向循环链表 单向循环链表(约瑟夫循环) 多项式相加 程序源代码 单链表.单向循环链表结点类 package javab; public class Node { int data; Node next; public Node(int data){ this.data=data; } } 第一题代码: package javab; import java.util.Scanner; public class I