对于二叉树而言,有如下特性:
1.第i层上,最多有2^(i-1)个节点。
2.高度为k的二叉树,最多有2^k-1个节点。
3.假设叶子数目为n0,度为2的节点数目为n2,则有:n0= n2+1
1.二叉树的插入
#include <stdio.h>
#include <stdlib.h>
#include "drawtree.h"
// 二叉树数据节点
typedef struct node
{
int data; // 数据域
struct node *lchild; //左子树指针
struct node *rchild; //右子树指针
}node;
//二叉树插入
node *bst_insert(node *root, int new_data);
// 前序遍历: 根节点 - 左子树 - 右子树
void pre_traval(node *root);
// 中序遍历:左子树 - 根节点 - 右子树
void mid_traval(node *root);
// 后序遍历:左子树 - 右子树 - 根节点
void lst_traval(node *root);
int main()
{
// 1.初始化空二叉树
node *root = NULL;
// 插入数据
root = bst_insert(root, 10);
root = bst_insert(root, 5);
root = bst_insert(root, 15);
root = bst_insert(root, 3);
root = bst_insert(root, 8);
root = bst_insert(root, 7);
root = bst_insert(root, 9);
root = bst_insert(root, 20);
root = bst_insert(root, 18);
// 2.数据操作
int cmd;
while(1)
{
printf("Pls Input: ");
scanf("%d", &cmd); while(getchar()!='\n');
if(cmd != 0) //二叉树插入
root = bst_insert(root, cmd);
else if(cmd == 0) // 遍历
{
printf("pre_traval: ");
pre_traval(root); // 前序遍历
printf("\n");
printf("mid_traval: ");
mid_traval(root); // 中序遍历
printf("\n");
printf("lst_traval: ");
lst_traval(root); // 后序遍历
printf("\n");
}
draw((_treenode *)root);
}
return 0;
}
// 前序遍历: 根节点-左子树-右子树
void pre_traval(node *root)
{
if(root == NULL)
return;
printf("%d ", root->data);
pre_traval(root->lchild);
pre_traval(root->rchild);
}
// 中序遍历:左子树 - 根节点 - 右子树
void mid_traval(node *root)
{
if(root == NULL)
return;
mid_traval(root->lchild);
printf("%d ", root->data);
mid_traval(root->rchild);
}
// 后序遍历:左子树 - 右子树 - 根节点
void lst_traval(node *root)
{
if(root == NULL)
return;
lst_traval(root->lchild);
lst_traval(root->rchild);
printf("%d ", root->data);
}
//二叉树插入
node *bst_insert(node *root, int new_data)
{
if(root == NULL)
{
// 如果当前根节点为NULL,说明找到了插入位置
node *new = malloc(sizeof(node));
new->data = new_data;
new->lchild = NULL;
new->rchild = NULL;
return new;
}
else if(root->data > new_data) // 如果新数据更小,往左子树插入
root->lchild = bst_insert(root->lchild, new_data);
else if(root->data < new_data) // 如果新数据更大,往右子树插入
root->rchild = bst_insert(root->rchild, new_data);
else // 如果相等,已存在,不作处理
printf("已存在\n");
return root;
}
2.二叉树查找
#include <stdio.h>
#include <stdlib.h>
#include "drawtree.h"
// 二叉树数据节点
typedef struct node
{
int data; // 数据域
struct node *lchild; //左子树指针
struct node *rchild; //右子树指针
}node;
//二叉树插入
node *bst_insert(node *root, int new_data);
// 二叉树搜索
int bst_search(node *root, int find_data);
// 前序遍历: 根节点 - 左子树 - 右子树
void pre_traval(node *root);
// 中序遍历:左子树 - 根节点 - 右子树
void mid_traval(node *root);
// 后序遍历:左子树 - 右子树 - 根节点
void lst_traval(node *root);
int main()
{
// 1.初始化空二叉树
node *root = NULL;
// 插入数据
root = bst_insert(root, 10);
root = bst_insert(root, 5);
root = bst_insert(root, 15);
root = bst_insert(root, 3);
root = bst_insert(root, 8);
root = bst_insert(root, 7);
root = bst_insert(root, 9);
root = bst_insert(root, 20);
root = bst_insert(root, 18);
// 2.数据操作
int cmd;
while(1)
{
printf("Pls Input find_data: ");
scanf("%d", &cmd); while(getchar()!='\n');
if(cmd != 0) //二叉树搜索
{
if(bst_search(root, cmd) == 0)
printf("找到了\n");
else
printf("无此数据\n");
}
else if(cmd == 0) // 遍历
{
printf("pre_traval: ");
pre_traval(root); // 前序遍历
printf("\n");
printf("mid_traval: ");
mid_traval(root); // 中序遍历
printf("\n");
printf("lst_traval: ");
lst_traval(root); // 后序遍历
printf("\n");
}
draw((_treenode *)root);
}
return 0;
}
// 二叉树搜索
int bst_search(node *root, int find_data)
{
if(root == NULL) // 无此数据
return -1;
printf("find\n");
if(root->data == find_data) // 找到指定数据
return 0;
else if(find_data < root->data)
return bst_search(root->lchild, find_data);
else if(find_data > root->data)
return bst_search(root->rchild, find_data);
}
// 前序遍历: 根节点-左子树-右子树
void pre_traval(node *root)
{
if(root == NULL)
return;
printf("%d ", root->data);
pre_traval(root->lchild);
pre_traval(root->rchild);
}
// 中序遍历:左子树 - 根节点 - 右子树
void mid_traval(node *root)
{
if(root == NULL)
return;
mid_traval(root->lchild);
printf("%d ", root->data);
mid_traval(root->rchild);
}
// 后序遍历:左子树 - 右子树 - 根节点
void lst_traval(node *root)
{
if(root == NULL)
return;
lst_traval(root->lchild);
lst_traval(root->rchild);
printf("%d ", root->data);
}
//二叉树插入
node *bst_insert(node *root, int new_data)
{
if(root == NULL)
{
// 如果当前根节点为NULL,说明找到了插入位置
node *new = malloc(sizeof(node));
new->data = new_data;
new->lchild = NULL;
new->rchild = NULL;
return new;
}
else if(root->data > new_data) // 如果新数据更小,往左子树插入
root->lchild = bst_insert(root->lchild, new_data);
else if(root->data < new_data) // 如果新数据更大,往右子树插入
root->rchild = bst_insert(root->rchild, new_data);
else // 如果相等,已存在,不作处理
printf("已存在\n");
return root;
}
drawtree.h
///
//
// Copyright(C), 2013-2017, GEC Tech. Co., Ltd.
//
// 文件: lab/tree/headers/drawtree.h
// 日期: 2017-9
// 描述: 使用C语言写一页webpage展示二叉树
//
// 作者: Vincent Lin (林世霖) 微信公众号:秘籍酷
// 技术微店: http://weidian.com/?userid=260920190
// 技术交流: 260492823(QQ群)
//
///
#ifndef _DRAWTREE_H_
#define _DRAWTREE_H_
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 公共头文件 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <semaphore.h>
#include <fcntl.h>
#include <pthread.h>
/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 公共头文件 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
#define MAX(a, b) ({ \
typeof(a) _a = a; \
typeof(b) _b = b; \
(void)(&_a == &_b);\
_a > _b? _a : _b; \
})
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 默认二叉树节点 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
typedef struct _tree_node
{
int data;
struct _tree_node *lchild;
struct _tree_node *rchild;
#ifdef AVL
int height;
#endif
#ifdef RB
struct _tree_node *parent;
int color;
#endif
}_treenode, *_linktree;
/* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 默认二叉树节点 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */
/* ↓↓↓↓↓ 用户指定二叉树节点 ↓↓↓↓↓ */
#ifndef NODE
#define NODE _treenode
#endif
/* ↑↑↑↑↑ 用户指定二叉树节点 ↑↑↑↑↑ */
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
#ifndef QUEUE_NODE_DATATYPE
#define QUEUE_NODE_DATATYPE NODE *
#endif
typedef QUEUE_NODE_DATATYPE qn_datatype;
struct _queue_node
{
qn_datatype data;
struct _queue_node *next;
};
typedef struct
{
struct _queue_node *front;
struct _queue_node *rear;
#ifdef QUEUE_SIZE
int size;
#endif
}_queuenode, *_linkqueue;
static _linkqueue init_queue(void)
{
_linkqueue q = (_linkqueue)malloc(sizeof(_queuenode));
q->front = q->rear =
(struct _queue_node *)malloc(sizeof(struct _queue_node));
q->rear->next = NULL;
return q;
}
static bool is_empty_q(_linkqueue q)
{
return (q->front == q->rear);
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static bool out_queue(_linkqueue q, qn_datatype *pdata)
{
if(is_empty_q(q))
return false;
struct _queue_node *p = q->front;
q->front = q->front->next;
free(p);
*pdata = q->front->data;
return true;
}
static bool en_queue(_linkqueue q, qn_datatype data)
{
struct _queue_node *pnew;
pnew = (struct _queue_node *)malloc(sizeof(struct _queue_node));
if(pnew == NULL)
return false;
pnew->data = data;
pnew->next = NULL;
q->rear->next = pnew;
q->rear = pnew;
return true;
}
#ifdef QUEUE_SIZE
int queue_size(_linkqueue *q)
{
return q->size;
}
#endif
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static inline void pre_travel(NODE *root, void (*handler)(NODE *))
{
if(root == NULL)
return;
handler(root);
pre_travel(root->lchild, handler);
pre_travel(root->rchild, handler);
}
static inline void mid_travel(NODE *root, void (*handler)(NODE *))
{
if(root == NULL)
return;
mid_travel(root->lchild, handler);
handler(root);
mid_travel(root->rchild, handler);
}
static inline void post_travel(NODE *root, void (*handler)(NODE *))
{
if(root == NULL)
return;
post_travel(root->lchild, handler);
post_travel(root->rchild, handler);
handler(root);
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static inline void level_travel(NODE *root, void (*handler)(NODE *))
{
if(root == NULL)
return;
_linkqueue q;
q = init_queue();
en_queue(q, root);
NODE *tmp;
while(1)
{
if(!out_queue(q, &tmp))
break;
handler(tmp);
if(tmp->lchild != NULL)
en_queue(q, tmp->lchild);
if(tmp->rchild != NULL)
en_queue(q, tmp->rchild);
}
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static char page_begin[] = "<html><head><title>tree map"
"</title></head><body>"
"<table border=0 cellspacing"
"=0 cellpadding=0>";
static char line_begin[] = "<tr>";
static char line_end [] = "</tr>";
static char space [] = "<td> </td>";
static char underline [] = "<td style=\"border-bottom:"
"1px solid #58CB64\"> "
"</td>";
#ifdef RB
static char data_begin_red[] = "<td bgcolor=\"#FF0000\";style="
"\"border:1px sol"
"id #58CB64;background-colo"
"r:#DDF1D8;PADDING:2px;\" t"
"itle=\"level: 1\">";
static char data_begin_blk[] = "<td bgcolor=\"#000000\";style="
"\"border:1px sol"
"id #58CB64;background-colo"
"r:#DDF1D8;PADDING:2px;\" t"
"itle=\"level: 1\"><font color"
"=\"#FFFFFF\">";
static char data_end_red[] = "</td>";
static char data_end_blk[] = "</font></td>";
#else
static char data_begin[] = "<td style=\"border:1px sol"
"id #58CB64;background-colo"
"r:#DDF1D8;PADDING:2px;\" t"
"itle=\"level: 1\">";
static char data_end [] = "</td>";
#endif
static char page_end [] = "</table></body></html>";
#define MAX_NODES_NUMBER 100
#define FILENAME 32
static int central_order[MAX_NODES_NUMBER];
static void putunderline(int fd, int num)
{
int i;
for(i=0; i<num; i++)
{
write(fd, underline, strlen(underline));
}
}
static void putspace(int fd, int num)
{
int i;
for(i=0; i<num; i++)
{
write(fd, space, strlen(space));
}
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
#ifdef RB
static void putdata(int fd, NODE * p)
{
char s[50];
bzero(s, 50);
snprintf(s, 50, "%d", p->data);
switch(p->color)
{
case RED:
write(fd, data_begin_red, strlen(data_begin_red));
write(fd, s, strlen(s));
write(fd, data_end_red, strlen(data_end_red));
break;
case BLACK:
write(fd, data_begin_blk, strlen(data_begin_blk));
write(fd, s, strlen(s));
write(fd, data_end_blk, strlen(data_end_blk));
}
}
#else
static void putdata(int fd, int data)
{
char s[50];
bzero(s, 50);
snprintf(s, 50, "%d", data);
write(fd, data_begin, strlen(data_begin));
write(fd, s, strlen(s));
write(fd, data_end, strlen(data_end));
}
#endif
static int Index = 0;
static void create_index(NODE * root)
{
if(Index >= MAX_NODES_NUMBER-1)
return;
central_order[Index++] = root->data;
}
static int get_index(int data)
{
int i;
for(i=0; i<100; i++)
{
if(central_order[i] == data)
return i;
}
return -1;
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static void data_leftside(int fd, NODE * root, int spaces)
{
if(root == NULL)
return;
int s_line=0;
if(root->lchild != NULL)
{
s_line = get_index(root->data)-
get_index(root->lchild->data)-1;
}
putspace(fd, spaces-s_line);
putunderline(fd, s_line);
}
static int data_rightside(int fd, NODE * root)
{
if(root == NULL)
return 0;
int s_line=0;
if(root->rchild != NULL)
{
s_line = get_index(root->rchild->data)-
get_index(root->data)-1;
}
putunderline(fd, s_line);
return s_line;
}
static void start_page(int fd)
{
write(fd, page_begin, strlen(page_begin));
}
/* ↓↓↓↓↓↓↓↓↓↓↓↓↓ 画网页相关算法代码 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
static void end_page(int fd)
{
write(fd, page_end, strlen(page_end));
}
static void draw(NODE * root)
{
if(root == NULL)
return;
time_t t;
time(&t);
static char filename[FILENAME];
bzero(filename, FILENAME);
snprintf(filename, FILENAME, "1.html");
int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0644);
if(fd == -1)
{
perror("open() failed");
exit(1);
}
Index = 0;
mid_travel(root, create_index);
_linkqueue q = init_queue();
NODE * tmp = root;
int ndata = 1;
start_page(fd);
while(1)
{
write(fd, line_begin, strlen(line_begin));
int i, n = 0;
int nextline = 0;
for(i=0; i<ndata; i++)
{
int index = get_index(tmp->data);
data_leftside(fd, tmp, index-n);
#ifdef RB
putdata(fd, tmp);
#else
putdata(fd, tmp->data);
#endif
int rightline = data_rightside(fd, tmp);
if(tmp->lchild != NULL)
{
nextline++;
en_queue(q, tmp->lchild);
}
if(tmp->rchild != NULL)
{
nextline++;
en_queue(q, tmp->rchild);
}
if(!out_queue(q, &tmp))
return;
n = index + rightline;
n++;
}
write(fd, line_end, strlen(line_end));
ndata = nextline;
}
end_page(fd);
close(fd);
}
#endif
冒泡排序
#include <stdio.h>
void show_array(int len, int *a)
{
int i;
for(i=0; i<len; i++)
printf("%d ", a[i]);
printf("\n");
}
void bubble_sort(int len, int *a)
{
// 遍历次数:len-1
int i, j;
int temp;
int flag;
for(i=0; i<len-1; i++)
{
flag=0;
// 两两对比,左数大于右数则交换(次数: len-i-1)
for(j=0; j<len-i-1; j++)
{
if(a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
flag = 1;
}
}
printf("%d: ", i+1);
show_array(5, a);
// 如果没有发生数据交换,则说明已经是有序列
if(flag == 0)
break;
}
}
int main()
{
int arr[5] = {5, 4, 3, 2, 1};
show_array(5, arr);
bubble_sort(5, arr);
show_array(5, arr);
return 0;
}
插入排序-额外空间
#include <stdio.h>
void show_array(int len, int *a)
{
int i;
for(i=0; i<len; i++)
printf("%d ", a[i]);
printf("\n");
}
void insertion_sort(int len, int *a)
{
// 1.定义有序列数组,将第1个数据放入
int b[len];
b[0] = a[0];
// 2.将原始数据的每个数据与有序列中数据对比,找到插入位置pos
int i; // 原始数据操作下标
int j; // 向后移动变量
int pos; // 有序列对比下标
for(i=1; i<len; i++)
{
// 2.1 在有序列中循环找到插入位置pos后,break结束
for(pos=0; pos<i; pos++)
{
if(a[i] < b[pos])
break;
}
// 2.2 将pos后续数据向后移动(从最后开始)
for(j=i; j>pos; j--)
b[j] = b[j-1];
// 2.3 数据放入有序列中pos位置
b[pos] = a[i];
// 把中间过程的数据打印出来
printf("%d: ", i);
show_array(5, b);
}
// 3.将有序列数据覆盖无序列
for(i=0; i<len; i++)
a[i] = b[i];
}
int main()
{
int arr[5] = {2, 5, 3, 1, 4};
show_array(5, arr);
insertion_sort(5, arr);
show_array(5, arr);
return 0;
}
插入排序
#include <stdio.h>
void show_array(int len, int *a)
{
int i;
for(i=0; i<len; i++)
printf("%d ", a[i]);
printf("\n");
}
void insertion_sort(int len, int *a)
{
int swap; //无序列数下标
int pos;
int i;
// 逐个循环取得无序数
for(swap=1; swap<len; swap++)
{
// 1.暂存当前无序数
int temp = a[swap];
// 2.该无序数与有序列每个数据对比,找到插入位置pos
for(pos=0; pos<swap; pos++)
{
if(temp < a[pos])
break;
}
// 3.将pos后续数据逐个向后移动(从后开始)
int i;
for(i=swap; i>pos; i--)
a[i] = a[i-1];
// 4.将该无序数写入有序列
a[pos] = temp;
}
}
int main()
{
int arr[5] = {2, 5, 3, 1, 4};
show_array(5, arr);
// 不使用额外内存
insertion_sort(5, arr);
show_array(5, arr);
return 0;
}