线索二叉树:
链式二叉树中有很多空指针,可以让这些指针指向它的下一个节点(前中后),这样在遍历树时可以不用递归而是使用循环,可以提高树的遍历速度。
中序线过树点数据项:
数:
左子树
右子树
右子树指针标志:(真表示指向的是右子树,假表示指向的是下一个节点)
选择树(了解):
是一种完全二叉树,带比较的数据存储在最后一层,根节点是左右子树的其中一个,是他们的最大的或最小的,能快速找出最大值或最小值
堆:是一种完全二叉树,不适合链式存储。
大根堆:根节点比左右子树大
小根堆:根节点比左右子树小
特点:最顶层是最大值或最小值
数据项:
存储数据的内存首地址
容量
数量
运算:
创建
调整
插入
删除
空或满
堆可以实行优先排序的效果
关于线索二叉树的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct TreeNode
{
int data;
struct TreeNode* left;
struct TreeNode* right;
bool rclue; //定义标记线索
}TreeNode;
TreeNode* create_node(int data)
{
TreeNode* node = malloc(sizeof(TreeNode));
node->data = data;
node->left = NULL;
node->right = NULL;
node->rclue = false;//线索初始化为false;
return node;
}
void _insert_tree(TreeNode** root,TreeNode* node)
{
if(NULL == *root)
{
*root = node;
return;
}
if(node->data < (*root)->data)
_insert_tree(&(*root)->left,node);
else
_insert_tree(&(*root)->right,node);
}
void insert_tree(TreeNode** root,int data)//插入
{
_insert_tree(root,create_node(data));
}
void ldr_show(TreeNode* root)//中序遍历
{
if(NULL == root) return;
ldr_show(root->left);
printf("%d ",root->data);
ldr_show(root->right);
}
TreeNode* prev = NULL;
void create_clue(TreeNode* root)
{
if(NULL == root) return;
create_clue(root->left);
/*
if(NULL == root->left)//判断左子树是否还有值
{
root->left = prev;//树指向上一个
root->lclue = true;//标记生效
}
*/
if(NULL!=prev && NULL==prev->right)
{
prev->rclue = true;
prev->right = root;
}
prev = root;
create_clue(root->right);
}
void clue_show(TreeNode* node)
{
while(node)
{
while(node->left)
node = node->left;
printf("%d ",node->data);
while(node->rclue)
{
node = node->right;
printf("%d ",node->data);
}
node = node->right;
}
printf("\n");
}
int main(int argc,const char* argv[])
{
TreeNode* root = NULL;
for(int i = 0; i<10; i++)
{
int data = rand() % 100;
printf("%d ",data);
insert_tree(&root,data);
}
printf("\n");
ldr_show(root);
printf("-----------------\n");
create_clue(root);
clue_show(root);
}
关于堆的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
#define swap(a,b) {typeof(a) t=a; a=b; b=t;}
typedef struct Heap
{
TYPE* arr;
int cal;
int cnt;
}Heap;
// 创建堆
Heap* create_heap(int cal)
{
// 申请堆结构需要内存
Heap* heap = malloc(sizeof(Heap));
// 申请存储节点需要的内存,由计算双亲、左右子时需要从1开始,因此第一个位置不使用
heap->arr = malloc(sizeof(TYPE)*cal+1);
heap->cal = cal;
// 先加+1再使用
heap->cnt = 0;
return heap;
}
// 销毁堆
void destory_heap(Heap* heap)
{
// 释放存储节点的内存
free(heap->arr);
// 释放堆结构的内存
free(heap);
}
// 堆空
bool empty_heap(Heap* heap)
{
return !heap->cnt;
}
// 堆满
bool full_heap(Heap* heap)
{
return heap->cnt >= heap->cal;
}
// 添加
bool add_heap(Heap* heap,TYPE data)
{
if(full_heap(heap)) return false;
heap->arr[++heap->cnt] = data;
// 从下向上调整为堆结构
int i = heap->cnt;
while(i > 1)
{
if(heap->arr[i/2] < heap->arr[i])
{
swap(heap->arr[i/2],heap->arr[i]);
}
i /= 2;
}
printf("%d\n",heap->arr[1]);
}
// 删除
bool del_heap(Heap* heap)
{
if(empty_heap(heap)) return false;
// 把堆顶与最后一个节点交换
swap(heap->arr[1],heap->arr[heap->cnt]);
// 数量减1,就相当于删除的堆
heap->cnt--;
// 从上往下进行调整
int i=1;
while(i <= heap->cnt)
{
// 保证有右子树,把左右子树中较大到交换到左子树中
if(i*2+1 <= heap->cnt && heap->arr[i*2] < heap->arr[i*2+1])
{
swap(heap->arr[i*2],heap->arr[i*2+1]);
}
// 保证有左子树,把左子树与根中较大的交换到根中
if(i*2 <= heap->cnt && heap->arr[i] < heap->arr[i*2])
{
swap(heap->arr[i*2],heap->arr[i]);
i *= 2;
}
else
{
// 没有左右子树超出范围
// 根比左右子树都要大,已经调整到合适位置
break;
}
}
}
// 遍历
void show_heap(Heap* heap)
{
for(int i=1; i<=heap->cal; i++)
{
printf("%d ",heap->arr[i]);
}
printf("\n");
}
int main(int argc,const char* argv[])
{
Heap* heap = create_heap(10);
for(int i=0; i<10; i++)
{
int data = rand() % 100;
add_heap(heap,data);
}
do{
show_heap(heap);
}while(del_heap(heap));
}