树形结构相关概念
1> 树形结构:表示数据元素之间存在一对多的关系
2> 树:是由一个根结点和多个子树构成的树形结构
3> 节点:就是树中的数据元素
4> 父亲结点:当前结点的直接上级节点
5> 孩子节点:当前结点的直接下级节点
6> 祖先结点:当前结点的直接或间接上级节点
7> 子孙节点:当前结点的直接或间接下级节点
8> 兄弟节点:拥有相同父结点的所有节点互称为兄弟节点
9> 堂兄弟节点:其父结点在同一层的所有节点,互为堂兄弟节点
10> 根结点:没有父结点的节点
11> 叶子节点:没有子节点的节点称为叶子节点
12> 分支节点:节点的度不为0的节点叫分支节点
13> 节点的度:就是当前结点的孩子节点个数,就称为节点的度
14> 树的度:就是树中节点的度的最大值
15> 节点的层次:从根结点开始到当前结点所经历的层数称为该节点的层次
16> 树的层次:每个节点的层次的最大值

二叉树
1> 二叉树:由根结点和最多两个子树组成,并且严格区分左右子树的树形结构
2> 左子树:由当前结点的左孩子节点为根结点构成的二叉树
3> 右子树:由当前结点的右孩子节点为根结点构成的二叉树
4> 满二叉树:二叉树的最后一层全是叶子节点,在没有添加层数的条件下,不能在向该树中增加节点的树
(除了最后一层为叶子节点外,其余层中的节点的度全为2)
5> 完全二叉树:在一棵满二叉树的基础上,最后一层自右向左逐渐减少节点的二叉树
二叉树的状态

1> 在二叉树的第 i 层上最多有 2^(i-1)个节点
2> 在二叉树的前n层最多有 2^n - 1个节点
3> 在二叉树中,叶子节点的个数,总比度为2的节点个数多 1


#include"btree.h"
#include<myhead.h>
//创建二叉树
NodePtr tree_create()
{
char ch = 0; //数据域的值
scanf("%c", &ch);
getchar(); //吸收回车
//判断当前子树是否为空
if(ch == '#')
{
return NULL; //递归出口
}
//说明子树不为空
NodePtr B = (NodePtr)malloc(sizeof(Node));
if(NULL==B)
{
return NULL;
}
//将数据封装到数据域中
B->data = ch;
//递归创建左子树
B->L = tree_create();
//递归创建右子树
B->R = tree_create();
return B; //将创建号的子树返回
}
二叉树的遍历:
先序遍历:先访问根结点,然后访问左孩子节点最后访问右孩子节点
中序遍历:先访问左孩子节点,访问根结点,最后访问右孩子节点
后序遍历:先访问左孩子,再访问右孩子,最后访问根结点
//先序遍历
void pri_order(NodePtr B)
{
//判断逻辑
if(NULL == B)
{
return; //递归出口
}
//输出数据域
printf("%c\t", B->data);
//调用函数先序输出左子树
pri_order(B->L);
//调用函数先序输出右子树
pri_order(B->R);
}
void mid_order(NodePtr B)
{
//判断逻辑
if(NULL == B)
{
return; //递归出口
}
//调用函数先序输出左子树
mid_order(B->L);
//输出数据域
printf("%c\t", B->data);
//调用函数先序输出右子树
mid_order(B->R);
}
//后序遍历
void post_order(NodePtr B)
{
//判断逻辑
if(NULL == B)
{
return; //递归出口
}
//调用函数先序输出左子树
post_order(B->L);
//调用函数先序输出右子树
post_order(B->R);
//输出数据域
printf("%c\t", B->data);
}
练习:
1、根据给出的二叉树序列画出该二叉树的图,并给出后序序列
前序遍历的顺序是: CABGHEDF
中序遍历的顺序是: GHBACDEF


算法
所谓算法就是计算机解决问题的方法和步骤
程序=数据结构+算法
特性
1> 确定性:算法的每一条语句都有确定的含义,不能模棱两可
2> 有穷性:程序执行一定时间后会自动结束的性质
3> 输入:至少有0个或多个输入,这里的输入,不限于输入语句
4> 输出:至少一个或多个输出,这里的输出,不限于输出语句
5> 可行性:经济可行性、社会可行性
算法的设计要求
1> 正确性:对所有正确的输入数据都能得到对应正确的结果
2> 健壮性:对不合法的输入数据,能够给出合理的输出,例如 switch中的default模块
3> 可读性:要求核心代码有注释、命名要规范、代码有缩进等等
4> 高效率:要求算法的时间复杂度要低
5> 低存储:要求空间复杂度要低
时间复杂度
时间复杂度是一个算法的时间量度,正常情况下,没有办法使用时间来衡量一个算法的。
由于代码行数和一个程序执行的时间成正比,所以我们就粗略得使用基本代码行与时间构建起一个对应关系式,该关系就是时间复杂度/


插入排序
//定义直接插入排序
void insert_sort(int *arr, int len)
{
//定义循环变量
int i,j;
for(i=1; i<len; i++) //遍历待排序序列
{
//此处,arr[i]就是第i趟中,待排序序列的第一个
int temp = arr[i]; //备份一下
//将temp元素在前面的已排序序列中找到位置后插入
for(j=i-1; temp<=arr[j]&&j>=0; j-- )
{
//将当前的元素后移
arr[j+1] = arr[j];
}
//将备份的数据放入arr[j+1]
arr[j+1] = temp;
}
printf("排序成功\n");
}
快速排序
1.定义:快速排序是在序列元素与选定基准元素比较分割大小两部分的交换排序
2.从待排序列中任取一个基准元素 与基准元素比较将待排序列分割为大小两部分 再对各部分重新选择基准元素并依此规则排序 直到每个部分只剩一个元素为止

//定义一趟快排的函数
int part(int *arr, int i, int j)
{
int x = arr[i]; //选定基准
while(i<j){ //循环继续,直到直到基准位置
while(arr[j]>=x && i<j ) //i<j防止错过
{ j--; //继续判断前面的元素
}
arr[i] = arr[j]; //将小的元素向前放
while(arr[i]<=x && i<j )
{ i++; //继续判断后面的元素
}
arr[j] = arr[i]; //将大的元素向后放
}
arr[i] = x; //将基准放入
return i; //将基准的下标返回
}
//定义快排函数
void quick_sort(int *arr, int low, int high)
{
if(low>=high)
{
return; //递归出口
}
//此处表示要排序的元素不只一个
int mid = part(arr, low, high); //对整体进行一次快排
//mid表示排序后的基准位置
//[low, mid-1] [mid+1, high]
//对基准左侧的部分进行快排
quick_sort(arr, low, mid-1);
//对基准右侧的数据进行快排
quick_sort(arr, mid+1, high);
}

941

被折叠的 条评论
为什么被折叠?



