C和指针 第十七章 经典数据类型 堆栈 队列 二叉树
堆栈:
//
// Created by mao on 16-9-16.
// #ifndef UNTITLED_STACK_H
#define UNTITLED_STACK_H
#define TRUE 1
#define FALSE 0 typedef int STACK_TYPE;
typedef struct stack{
STACK_TYPE value;
struct stack *next;
} STACK; void create_stack();
void destory_stack();
void push(STACK_TYPE value);
STACK_TYPE pop();
int isEmpty();
#endif //UNTITLED_STACK_H
stack.h
//
// Created by mao on 16-9-16.
//
#include <stdlib.h>
#include "stack.h" static STACK *stack; void create_stack()
{
stack = (STACK *)malloc(sizeof(STACK));
stack -> next = NULL;
} void destory_stack()
{
STACK *pStack;
while((pStack = stack -> next) != NULL){
free(stack);
stack = pStack;
}
} void push(STACK_TYPE value)
{
STACK *new = (STACK *)malloc(sizeof(STACK));
new -> next = stack;
new -> value = value;
stack = new;
} STACK_TYPE pop()
{
STACK_TYPE value = stack -> value;
STACK *pStack = stack;
stack = stack -> next;
free(pStack);
return value;
} int isEmpty()
{
return stack -> next == NULL ? TRUE : FALSE;
}
stack.c
#include <stdio.h>
#include "stack.h" int main()
{
//堆栈
create_stack();
push(10);
push(20);
push(30);
pop();
push(22);
while(isEmpty() == FALSE){
printf("%d \t", pop());
}
}
main.c
运行:
队列:
当使用数组作为队列时,如果只是一端插入一端弹出,那么当尾部没有空间时,便无法插入元素,一种解决方法是使用“环绕”数组,新元素可以存储到以前删除元素所留出来的空间中,这种方法称为循环数组。
循环数组有个问题,当队列为空,或者为满时,首位的下标是一样的,无法判断出此时队列的状态,所以在队列的rear后加一个空余的不使用的位置,用来判断队列的状态是满队列,还是空队列。
当为满队列时:
(rear + 2) % QUEUE_SIZE = front
当为空队列时:
(rear + 1) % QUEUE_SIZE = front
队列实现:
//
// Created by mao on 16-9-16.
// #ifndef UNTITLED_QUEUE_H
#define UNTITLED_QUEUE_H
#define TRUE 1
#define FALSE 0
#define QUEUE_SIZE 100
#define ARRAY_SIZE (QUEUE_SIZE + 1)
typedef int QUEUE_TYPE; static QUEUE_TYPE queue[ARRAY_SIZE];
static int front = 1;
static int rear = 0; void Q_delete();
QUEUE_TYPE Q_first();
void Q_insert(QUEUE_TYPE value);
int Q_isEmpty();
int Q_isFull();
#endif //UNTITLED_QUEUE_H
queue.h
//
// Created by mao on 16-9-16.
// #include "queue.h"
#include <assert.h> void Q_delete()
{
assert(Q_isEmpty() == FALSE);
front = (front + 1) % QUEUE_SIZE;
front = (front) % QUEUE_SIZE;
} QUEUE_TYPE Q_first()
{
assert(Q_isEmpty() == FALSE);
return queue[front];
} //队列插入数据,rear++
void Q_insert(QUEUE_TYPE value)
{
assert(Q_isFull() == FALSE);
rear = (rear + 1) % QUEUE_SIZE;
queue[(rear) % QUEUE_SIZE] = value;
} int Q_isEmpty()
{
return (rear + 1) % QUEUE_SIZE == front ? TRUE: FALSE;
} int Q_isFull()
{
return (rear + 2) % QUEUE_SIZE == front ? TRUE : FALSE;
}
queue.c
#include <stdio.h>
#include "queue.h" int main()
{ //插入队列
Q_insert(10);
Q_insert(12);
Q_delete();
Q_insert(22);
Q_insert(30);
printf("%d\n", Q_first());
Q_delete();
printf("%d\n", Q_first());
Q_delete();
printf("%d\n", Q_first());
Q_delete(); return 1;
}
main.c
运行:
二叉树:
#ifndef UNTITLED_BINARYTREE_H
#define UNTITLED_BINARYTREE_H #include <assert.h>
#define TREE_TYPE int
#define ARRAY_SIZE 100
#define TREE_SIZE (ARRAY_SIZE + 1)
TREE_TYPE TREE[TREE_SIZE] = {0}; static unsigned int leftChild(unsigned int current)
{
return current * 2;
} static unsigned int rightChild(unsigned int current)
{
return current * 2 + 1;
} void insert(TREE_TYPE value)
{
unsigned int current = 1;
while(TREE[current] != 0){
if(value < TREE[current]){
current = leftChild(current);
}else{
assert(TREE[current] != value);
current = rightChild(current);
}
assert(current < TREE_SIZE);
}
TREE[current] = value;
} TREE_TYPE *find(TREE_TYPE value)
{
unsigned int current = 1;
while (current < TREE_SIZE && TREE[current] != value){
if(value < TREE[current]){
current = leftChild(current);
}else if(value > TREE[current]){
current = rightChild(current);
}
}
if(current < TREE_SIZE){
return TREE + current;
}else{
return 0;
}
} //根据指针计算数组下标
static unsigned long getIndex(TREE_TYPE *ptr){
assert(ptr >= TREE || ptr <= TREE + TREE_SIZE);
return ptr - TREE;
} //内置先遍历接口
void pre_order_traverse(unsigned int current, void(*callback)(TREE_TYPE value))
{
if(current < ARRAY_SIZE && TREE[current] != 0){
callback(TREE[current]);
pre_order_traverse(leftChild(current), callback);
pre_order_traverse(rightChild(current), callback);
}
} //先序遍历
void do_pre_traverse(void(*callback)(TREE_TYPE value))
{
pre_order_traverse(1, callback);
}
//中序遍历
void mid_order_traverse(unsigned int current, void(*callback)(TREE_TYPE value))
{
if(current < ARRAY_SIZE && TREE[current] != 0){
mid_order_traverse(leftChild(current), callback);
callback(TREE[current]);
mid_order_traverse(rightChild(current), callback);
}
} void do_mid_order_traverse(void(*callback)(TREE_TYPE value))
{
mid_order_traverse(1, callback);
} //后续遍历
void after_order_traverse(unsigned int current, void(*callback)(TREE_TYPE value))
{
if(current < ARRAY_SIZE && TREE[current] != 0){
after_order_traverse(leftChild(current), callback);
after_order_traverse(rightChild(current), callback);
callback(TREE[current]);
}
} void do_after_order_traverse(void(*callback)(TREE_TYPE value))
{
after_order_traverse(1, callback);
} void print_tree(TREE_TYPE value)
{
printf("%d\t", value);
} #endif //UNTITLED_BINARYTREE_H
BinaryTree.h
#include <stdio.h>
#include "BinaryTree.h" int main()
{
insert(20);
insert(12);
insert(5);
insert(9);
insert(16);
insert(17);
insert(25);
insert(28);
insert(26);
insert(29); do_pre_traverse(print_tree);
printf("\n");
do_mid_order_traverse(print_tree);
printf("\n");
do_after_order_traverse(print_tree);
return 1;
}
main.c
运行:
数组形式存放二叉树,会导致内存空间的浪费,尤其是非对称的二叉树,会造成大量的数组空间闲置。通过链式二叉树可以解决数组不充分的问题
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> typedef int TREE_TYPE;
typedef struct TREE_NODE {
TREE_TYPE value;
struct TREE_NODE *leftPtr;
struct TREE_NODE *rightPtr;
} TREE_NODE;
//指向树的根节点的指针
TREE_NODE *root; //创建根节点
void createTree(TREE_TYPE value)
{
root = (TREE_NODE *) malloc(sizeof(TREE_NODE));
root -> leftPtr = NULL;
root -> rightPtr = NULL;
root -> value = value;
} TREE_NODE * getRoot()
{
return root;
} //插入节点
void insertNode(TREE_TYPE value)
{
TREE_NODE *current = root;
//pos为待插入节点的父节点
TREE_NODE *parent = root;
while(current != NULL){
//保存父节点信息
parent = current;
if(current -> value < value){
current = current -> rightPtr;
}else if(current -> value > value){
current = current -> leftPtr;
}else{
//节点已存在
return ;
}
}
TREE_NODE *node = (TREE_NODE *) malloc(sizeof(TREE_NODE));
assert(node != NULL);
node -> leftPtr = NULL;
node -> rightPtr = NULL;
node -> value = value;
//根据值得大小判断,node应该放在左节点还是右节点
if(parent -> value > value){
parent -> leftPtr = node;
}else{
parent -> rightPtr = node;
}
} TREE_NODE * findNode(TREE_TYPE value)
{
TREE_NODE *current = root;
while(current != NULL && current -> value != value){
if( current -> value > value){
current = current -> leftPtr;
}else{
current = current -> rightPtr;
}
}
return current;
} void printNode(TREE_NODE * node)
{
printf("%d\t", node -> value);
} void pre_order_traverse(TREE_NODE * current)
{
if(current != NULL){
printNode(current);
pre_order_traverse(current -> leftPtr);
pre_order_traverse(current -> rightPtr);
}
} void mid_order_traverse(TREE_NODE * current)
{
if(current != NULL){
mid_order_traverse(current -> leftPtr);
printNode(current);
mid_order_traverse(current -> rightPtr);
}
} void after_order_traverse(TREE_NODE * current)
{
if(current != NULL){
after_order_traverse(current -> leftPtr);
after_order_traverse(current -> rightPtr);
printNode(current);
}
}
BinaryTree.h
#include <stdio.h>
#include "BinaryTree.h" int main()
{
createTree(20);
insertNode(12);
insertNode(5);
insertNode(9);
insertNode(16);
insertNode(17);
insertNode(25);
insertNode(28);
insertNode(26);
insertNode(29); pre_order_traverse(root);
printf("\n");
mid_order_traverse(root);
printf("\n");
after_order_traverse(root); return 1;
}
BinaryTree.c
运行:
C和指针 第十七章 经典数据类型 堆栈 队列 二叉树的更多相关文章
- C和指针 第十七章 习题
17.8 为数组形式的树编写模块,用于从树中删除一个值,如果没有找到,程序节点 ArrayBinaryTree.c // // Created by mao on 16-9-18. // #inclu ...
- C和指针 第十七章 二叉树删除节点
二叉树的节点删除分为三种情况: 1.删除的节点没有子节点,直接删除即可 2. 删除的节点有一个子节点,直接用子节点替换既可以 3.删除的节点有两个子节点. 对于第三种情况,一般是不删除这个节点,而是删 ...
- 第二十七章 system v消息队列(三)
消息队列实现回射客户/服务器 msg_srv.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> ...
- 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索
第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...
- Gradle 1.12 翻译——第十七章. 从 Gradle 中调用 Ant
有关其他已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或访问:http://gradledoc.qiniudn.com ...
- Linux内核设计第十七章笔记
第十七章 设备与模块 关于设备驱动和设备管理,四种内核成分 设备类型:在所有unix系统中为了统一普通设备的操作所采用的分类 模块:Linux内核中用于按需加载和卸载目标代码的机制 内核对象:内核数据 ...
- 【C++】《C++ Primer 》第十七章
第十七章 标准库特殊设施 一.tuple类型 tuple是类似pair的模板,每个pair的成员类型都不相同,但每个pair都恰好有两个成员. 不同的tuple类型的成员类型也不相同,一个tuple可 ...
- 《Go语言圣经》阅读笔记:第三章基础数据类型
第三章 基础数据类型 Go语言将数据类型分为四类: 基础类型 数字 整数 浮点数 复数 字符串 布尔 复合类型 数据 结构体 引用类型 指针 切片 字典 函数 通道 接口类型 在此章节中先介绍基础类型 ...
- 进击的Python【第十七章】:jQuery的基本应用
进击的Python[第十七章]:jQuery的基本应用
随机推荐
- 平常看到的Alt+xx 快捷键用法
1. 先按Alt, 哪一个菜单对应的字符是有划线的. 2. 输入对应的字符打开相应的菜单, 3 再输入相应的字符打开子菜单
- Node.js起步 -- (1)
先来简单介绍nodeJS 我们知道JavaScript是运行在浏览器中的,浏览器为它提供了一个上下文(context),从而让JavaScript得以解析执行. nodeJS其实可以这么理解,它是另外 ...
- [开源].NET数据库访问框架Chloe.ORM
扯淡 13年毕业之际,进入第一家公司实习,接触了 EntityFramework,当时就觉得这东西太牛了,访问数据库都可以做得这么轻松.优雅!毕竟那时还年轻,没见过世面.工作之前为了拿个实习机会混个工 ...
- 对于一个div下两个横内元素对其或者居中的方法
我们会经常遇到这样的对其问题图片和文字,或者文字和单选按钮之类的,而且,如果文字不是12px或者14px,有时候想大一点的时候,会出现对不起的情况或者居中不了. 下面我们来看看: 有时候会出现: 这种 ...
- 用信息值进行特征选择(Information Value)
Posted by c cm on January 3, 2014 特征选择(feature selection)或者变量选择(variable selection)是在建模之前的重要一步.数据接口越 ...
- CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置
1.安装MariaDB 安装命令 yum -y install mariadb mariadb-server 安装完成MariaDB,首先启动MariaDB,两条命令都可以 systemctl sta ...
- 使用Eclipse进行远程调试
转自:http://blog.csdn.net/sunyujia/article/details/2614614 今天决定做件有意义的事,写篇图文并茂的blog,为什么要图文并茂?因为很多事可能用语言 ...
- 数据可视化 echarts3
初识 echarts ECharts,一个纯 Javascript 的数据可视化图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefo ...
- iOS-RunLoop
简单的说run loop是事件驱动的一个大循环,如下代码所示int main(int argc, char * argv[]) { //程序一直运行状态 while (AppIsRun ...
- 架构师养成记--8.Queue
一.ConcurrentLinkedQueue 是一个适合在高并发场景下,无锁,无界的,先进先出原则.不允许为null值,add().offer()加入元素,这两个方法没区别:pull().peek( ...