vi正常模式下:
"shift + g" 跳到最后一行
"gg" 跳到第一行
<效率更高的双向链表结构代码>
-
/*代码*/ 01link.c
-
#include <stdlib.h>
-
#include "01link.h"
-
//链表初始化
-
void link_init(Link *p_link) {
-
p_link->head.p_next = &(p_link->tail);
-
p_link->tail.p_prev = &(p_link->head);
-
p_link->tail.p_next = NULL;
-
p_link->head.p_prev = NULL;
-
p_link->p_cur = NULL;
-
}
-
//链表清理
-
void link_deinit(Link *p_link) {
-
while(p_link->head.p_next != &(p_link->tail)) {
-
Node *p_first = &(p_link->head);
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
p_first->p_next = p_last;
-
p_last->p_prev = p_first;
-
free(p_mid);
-
p_mid = NULL;
-
}
-
p_link->p_cur = NULL;
-
}
-
//统计有效节点数据个数
-
int link_size(const Link *p_link) {
-
int cnt = 0;
-
const Node *p_node = NULL;
-
for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {
-
const Node *p_first = p_node;
-
const Node *p_mid = p_first->p_next;
-
const Node *p_last = p_mid->p_next;
-
cnt++;
-
}
-
return cnt - 1;
-
}
-
//把新数字加入到最前面,num代表要加入的数字
-
void link_add_head(Link *p_link, int num) {
-
Node *p_first = NULL, *p_mid = NULL, *p_last = NULL;
-
Node *p_node = (Node *)malloc(sizeof(Node));
-
if(!p_node) {
-
return ;
-
}
-
p_node->num = num;
-
p_node->p_next = NULL;
-
p_node->p_prev = NULL;
-
p_first = &(p_link->head);
-
p_mid = p_first->p_next;
-
p_last = p_mid->p_next;
-
p_first->p_next = p_node;
-
p_node->p_prev = p_first;
-
p_node->p_next = p_mid;
-
p_mid->p_prev = p_node;
-
p_link->p_cur = NULL;
-
}
-
//把新数字加入到最后面(追加),num代表要加入的数字
-
void link_append(Link *p_link, int num) {
-
Node *p_tmp = NULL; //循环指针变量
-
Node *p_node = (Node *)malloc(sizeof(Node));
-
if(!p_node) {
-
return ;
-
}
-
p_node->num = num;
-
p_node->p_next = NULL;
-
p_node->p_prev = NULL;
-
for(p_tmp = &(p_link->head); p_tmp != &(p_link->tail); p_tmp = p_tmp->p_next) {
-
Node *p_first = p_tmp;
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
if(p_mid == &(p_link->tail)) {
-
p_first->p_next = p_node;
-
p_node->p_prev = p_first;
-
p_node->p_next = p_mid;
-
p_mid->p_prev = p_node;
-
break;
-
}
-
}
-
p_link->p_cur = NULL;
-
}
-
//按顺序加入新数字
-
void link_insert_in_order(Link *p_link, int num) {
-
Node *p_tmp = NULL;
-
Node *p_node = (Node *)malloc(sizeof(Node));
-
if(!p_node) {
-
return ;
-
}
-
p_node->num = num;
-
p_node->p_next = NULL;
-
p_node->p_prev = NULL;
-
for(p_tmp = &(p_link->head); p_tmp != &(p_link->tail); p_tmp = p_tmp->p_next) {
-
Node *p_first = p_tmp;
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
if(p_mid == &(p_link->tail) || p_mid->num > num) {
-
p_first->p_next = p_node;
-
p_node->p_prev = p_first;
-
p_node->p_next = p_mid;
-
p_mid->p_prev = p_node;
-
break;
-
}
-
}
-
p_link->p_cur = NULL;
-
}
-
//删除最前面数字的函数
-
void link_remove_head(Link *p_link) {
-
Node *p_first = &(p_link->head);
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
if(p_mid == &(p_link->tail)) {
-
return ;
-
}
-
p_first->p_next = p_last;
-
p_last->p_prev = p_first;
-
free(p_mid);
-
p_mid = NULL;
-
p_link->p_cur = NULL;
-
}
-
//删除最后一个数字的函数
-
void link_remove_tail(Link *p_link) {
-
Node *p_node = NULL;
-
for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {
-
Node *p_first = p_node;
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
if(p_last == &(p_link->tail)) {
-
p_first->p_next = p_last;
-
p_last->p_prev = p_first;
-
free(p_mid);
-
p_mid = NULL;
-
break;
-
}
-
}
-
p_link->p_cur = NULL;
-
}
-
//删除某个数字的函数
-
void link_remove(Link *p_link, int num) {
-
Node *p_node = NULL;
-
for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {
-
Node *p_first = p_node;
-
Node *p_mid = p_first->p_next;
-
Node *p_last = p_mid->p_next;
-
if(p_mid != &(p_link->tail) && p_mid->num == num) {
-
p_first->p_next = p_last;
-
p_last->p_prev = p_first;
-
free(p_mid);
-
p_mid = NULL;
-
break;
-
}
-
}
-
p_link->p_cur = NULL;
-
}
-
//获得第一个数字的函数
-
int link_get_head(const Link *p_link, int *p_num) {
-
if(p_link->head.p_next == &(p_link->tail)) {
-
return 0;
-
}
-
else {
-
*p_num = p_link->head.p_next->num;
-
return 1;
-
}
-
}
-
//获得最后一个数字的函数
-
int link_get_tail(const Link *p_link, int *p_num) {
-
const Node *p_node = NULL;
-
if(p_link->head.p_next == &(p_link->tail)) {
-
return 0;
-
}
-
for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {
-
const Node *p_first = p_node;
-
const Node *p_mid = p_first->p_next;
-
const Node *p_last = p_mid->p_next;
-
if(p_last == &(p_link->tail)) {
-
*p_num = p_mid->num;
-
return 1;
-
}
-
}
-
}
-
//获得某个编号的数字的函数,num表示编号,*p_num获得的数字
-
int link_get(const Link *p_link, int num, int *p_num) {
-
int cnt = 0;
-
const Node *p_node = NULL;
-
for(p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->p_next) {
-
const Node *p_first = p_node;
-
const Node *p_mid = p_first->p_next;
-
const Node *p_last = p_mid->p_next;
-
if(p_mid != &(p_link->tail) && cnt == num) {
-
*p_num = p_mid->num;
-
return 1;
-
}
-
cnt++;
-
}
-
return 0;
-
}
-
//开始从前向后遍历(准备开始调用link_add_head函数)
-
void link_begin(Link *p_link) {
-
p_link->p_cur = &(p_link->head);
-
}
-
//在从前向后的遍历过程中获得下一个数字
-
int link_next(Link *p_link, int *p_num) {
-
//如果指针是空就表示没有数据
-
if(!(p_link->p_cur)) {
-
return 0;
-
}
-
p_link->p_cur = p_link->p_cur->p_next; //指针向后移动一步
-
if(p_link->p_cur == &(p_link->tail)) { //指针和尾节点捆绑
-
p_link->p_cur = NULL; //指针恢复到开始之前的样子
-
return 0;
-
}
-
else {
-
*p_num = p_link->p_cur->num; //指针有效节点捆绑
-
return 1;
-
}
-
}
-
//开始从后向前遍历
-
void link_rbegin(Link *p_link) {
-
p_link->p_cur = &(p_link->tail);
-
}
-
//在从后向前的遍历过程中获得下一个数字
-
int link_prev(Link *p_link, int *p_num) {
-
if(!(p_link->p_cur)) {
-
return 0;
-
}
-
p_link->p_cur = p_link->p_cur->p_prev; //指针向前移动一步
-
if(p_link->p_cur == &(p_link->head)) {
-
p_link->p_cur = NULL;
-
return 0;
-
}
-
else {
-
*p_num = p_link->p_cur->num;
-
return 1;
-
}
-
}
-
/*代码*/ 01link.h
-
#ifndef __01LINK_H__
-
#define __01LINK_H__
-
#include <stdlib.h>
-
typedef struct Node{
-
int num;
-
struct Node *p_next;
-
struct Node *p_prev; //prev:上一个
-
} Node;
-
typedef struct {
-
Node head, tail;
-
Node *p_cur; //随着函数调用,该指针依次和每个数字捆绑
-
} Link;
-
void link_init(Link *); //链表初始化
-
void link_deinit(Link *); //链表清理
-
int link_size(const Link *); //统计有效节点数据个数
-
//把新数字加入到最前面,num代表要加入的数字
-
void link_add_head(Link *, int);
-
//把新数字加入到最后面(追加),num代表要加入的数字
-
void link_append(Link *, int);
-
//按顺序加入新数字
-
void link_insert_in_order(Link *, int);
-
//删除最前面数字的函数
-
void link_remove_head(Link *);
-
//删除最后一个数字的函数
-
void link_remove_tail(Link *);
-
//删除某个数字的函数
-
void link_remove(Link *, int);
-
//获得第一个数字的函数
-
int link_get_head(const Link *, int *);
-
//获得最后一个数字的函数
-
int link_get_tail(const Link *, int *);
-
//获得某个编号的数字的函数,num表示编号,*p_num获得的数字
-
int link_get(const Link *, int, int *);
-
//开始从前向后遍历的函数
-
void link_begin(Link *);
-
//在从前向后的遍历中获得下一个数字的函数
-
int link_next(Link *, int *);
-
//在从后向前遍历的函数
-
void link_rbegin(Link *);
-
//在从后向前的遍历过程中获得下一个数字
-
int link_prev(Link *, int *);
-
#endif //__01LINK_H__
-
/*代码*/ 01main.c
-
#include <stdio.h>
-
#include "01link.h"
-
int main() {
-
int num = 0;
-
Link lnk = {0};
-
link_init(&lnk);
-
link_append(&lnk, 3);
-
link_append(&lnk, 5);
-
link_append(&lnk, 7);
-
link_append(&lnk, 9);
-
link_append(&lnk, 11);
-
link_begin(&lnk);
-
while(1) {
-
if(!link_next(&lnk, &num)) { //如果没拿到数字
-
break;
-
}
-
printf("%d ", num);
-
}
-
printf("\n");
-
link_rbegin(&lnk);
-
while(1) {
-
if(!link_prev(&lnk, &num)) {
-
break;
-
}
-
printf("%d ", num);
-
}
-
printf("\n");
-
link_deinit(&lnk);
-
return 0;
-
}
【树】
如果单向线性链式物理结构中每个节点可以向后找到多个其他节点,就成为了一棵"树"
树里的节点可以分成几层,"不同层之间符合线性规律"(任何两层之间都有前后顺序)
树的最上面一层只有一个节点,这个节点叫做"树的根节点"
可以"用根节点代表整棵树"
如果树中两个节点之间有直接的联系,就说明他们之间存在"父子关系"
靠近根节点的叫"父节点",远离根节点的叫"子节点"
任何节点"最多只能有一个父节点",但是"可以有多个子节点"
【二叉树】
如果每个节点"最多只有两个"子节点,就把这种树叫做"二叉树"
二叉树是最简单的树(所有的树都可以转化为二叉树)
二叉树里"用左右区分"一个节点的两个不同子节点
二叉树里任何一个节点都可以看作是一个二叉树的根节点
如果二叉树中一个节点叫 A ,它的左子节点叫 B 右子节点叫 C,则B所代表的二叉树叫做A的"左子树",C所代表的二叉树叫做A的"右子树"
树的遍历指的是:"依次处理树里的每一个节点"
树的大多数操作都是通过遍历实现的
通常采用"递归方式解决树的遍历"问题
在对树进行遍历的时候,一定"先遍历左"子树,然"后遍历右"子树
如果最先处理根节点叫做"前序遍历"
如果中间处理根节点叫做"中序遍历"
如果最后处理根节点叫做"后序遍历"
【练习】
编写函数计算一棵树的高度
-
/*代码*/ 01tree.h 头文件
-
#ifndef __01TREE_H__
-
#define __01TREE_H__
-
struct node;
-
typedef struct {
-
struct node *p_node;
-
} tree;
-
typedef struct node {
-
int num;
-
tree left;
-
tree right;
-
} node;
-
//树的初始化函数
-
void tree_init(tree *);
-
//树的清理函数
-
void tree_deinit(tree *);
-
//按顺序在树里插入新数字
-
void tree_insert_in_order(tree *, int );
-
//中序遍历函数
-
void miter(tree *, void (*)(int));
-
//前序遍历函数
-
void fiter(tree *, void (*)(int));
-
//后序遍历函数
-
void liter(tree *, void (*)(int));
-
//删除节点的函数
-
void tree_remove(tree *, int );
-
//计算树高度的函数
-
int tree_height(const tree *);
-
#endif //__01TREE_H__
-
/*代码*/ 01tree.c 函数源文件
-
#include <stdlib.h>
-
#include "01tree.h"
-
//树的初始化函数
-
void tree_init(tree *p_tree) {
-
p_tree->p_node = NULL;
-
}
-
//树的清理函数
-
void tree_deinit(tree *p_tree) {
-
if (!p_tree->p_node) {
-
return ;
-
}
-
tree_deinit(&(p_tree->p_node->left));
-
tree_deinit(&(p_tree->p_node->right));
-
free(p_tree->p_node);
-
p_tree->p_node = NULL;
-
}
-
//在有序二叉树里查找某个数字所在的位置
-
const tree *tree_search_in_order(const tree *p_tree, int num) {
-
if (!p_tree->p_node) {
-
return p_tree;
-
}
-
if (p_tree->p_node->num == num) {
-
return p_tree;
-
}
-
else if (p_tree->p_node->num > num) {
-
return tree_search_in_order(&(p_tree->p_node->left), num);
-
}
-
else {
-
return tree_search_in_order(&(p_tree->p_node->right), num);
-
}
-
}
-
//按顺序向有序二叉树中插入新数字
-
void tree_insert_in_order(tree *p_tree, int num) {
-
tree *p_tmp = (tree *)tree_search_in_order(p_tree, num);
-
if (!p_tmp->p_node) {
-
node *p_node = (node *)malloc(sizeof(node));
-
if (p_node) {
-
p_node->num = num;
-
p_node->left.p_node = NULL;
-
p_node->right.p_node = NULL;
-
p_tmp->p_node = p_node;
-
}
-
}
-
}
-
//按顺序把有序二叉树里所有数字显示
-
//在屏幕上
-
/*void tree_print(tree *p_tree) {
-
if (!p_tree->p_node) {
-
return ;
-
}
-
tree_print(&(p_tree->p_node->left));
-
printf("%d ", p_tree->p_node->num);
-
tree_print(&(p_tree->p_node->right));
-
}*/
-
//中序遍历函数
-
void miter(tree *p_tree, void (*p_func)(int)) {
-
if (!p_tree->p_node) {
-
return ;
-
}
-
miter(&(p_tree->p_node->left), p_func);
-
p_func(p_tree->p_node->num);
-
miter(&(p_tree->p_node->right), p_func);
-
}
-
//前序遍历函数
-
void fiter(tree *p_tree, void (*p_func)(int)) {
-
if (!p_tree->p_node) {
-
return ;
-
}
-
p_func(p_tree->p_node->num);
-
miter(&(p_tree->p_node->left), p_func);
-
miter(&(p_tree->p_node->right), p_func);
-
}
-
//后序遍历函数
-
void liter(tree *p_tree, void (*p_func)(int)) {
-
if (!p_tree->p_node) {
-
return ;
-
}
-
miter(&(p_tree->p_node->left), p_func);
-
miter(&(p_tree->p_node->right), p_func);
-
p_func(p_tree->p_node->num);
-
}
-
//删除节点的函数
-
void tree_remove(tree *p_tree, int num) {
-
node *p_node = NULL;
-
tree *p_tmp = (tree *)tree_search_in_order(p_tree, num);
-
if (!p_tmp->p_node) {
-
return ;
-
}
-
p_node = p_tmp->p_node;
-
if (!p_tmp->p_node->left.p_node) {
-
p_tmp->p_node = p_tmp->p_node->right.p_node;
-
}
-
else if (!p_tmp->p_node->right.p_node) {
-
p_tmp->p_node = p_tmp->p_node->left.p_node;
-
}
-
else {
-
tree *p_tmp1 = (tree *)tree_search_in_order(&(p_tmp->p_node->left), p_tmp->p_node->right.p_node->num);
-
p_tmp1->p_node = p_tmp->p_node->right.p_node;
-
p_tmp->p_node = p_tmp->p_node->left.p_node;
-
}
-
free(p_node);
-
p_node = NULL;
-
}
-
//计算树高度的函数
-
int tree_height(const tree *p_tree) {
-
int ret = 0, left_height = 0, right_height = 0;
-
if (!p_tree->p_node) {
-
return 0;
-
}
-
left_height = tree_height(&(p_tree->p_node->left));
-
right_height = tree_height(&(p_tree->p_node->right));
-
ret = left_height > right_height ? left_height : right_height;
-
return ret + 1;
-
}
-
/*代码*/ 01main.c 树的主函数
-
#include <stdio.h>
-
#include "01tree.h"
-
void print(int num) {
-
printf("%d ", num);
-
}
-
int main() {
-
tree tr = {0};
-
tree_init(&tr);
-
tree_insert_in_order(&tr, 50);
-
tree_insert_in_order(&tr, 30);
-
tree_insert_in_order(&tr, 70);
-
tree_insert_in_order(&tr, 15);
-
tree_insert_in_order(&tr, 40);
-
tree_insert_in_order(&tr, 60);
-
tree_insert_in_order(&tr, 80);
-
tree_insert_in_order(&tr, 7);
-
tree_insert_in_order(&tr, 21);
-
tree_insert_in_order(&tr, 100);
-
printf("树的高度是%d\n", tree_height(&tr));//树的高度是4
-
miter(&tr, print); //7 15 21 30 40 50 60 70 80 100
-
printf("\n");
-
tree_remove(&tr, 30);
-
miter(&tr, print); //7 15 21 40 50 60 70 80 100
-
printf("\n");
-
tree_deinit(&tr);
-
return 0;
-
}