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的基本应用
随机推荐
- 常用算法——排序(二)
简单选择排序法 选择排序(Selection Sort)的基本思想:对n个记录进行扫描,选择最小的记录,将其输出,接着在剩下的n-1个记录中扫描,选择最小的记录将其输出,--不断重复这个过程,直到只剩 ...
- 学习python函数笔记之一
1.函数文档字符串,用于存放函数的说明,一般写在第一行 2.函数调用:函数名+参数列表(函数的参数分实际参数和形式参数,str就是形式参数,则'welcome 头 python'就是实际参数) 参数需 ...
- [No0000A5]批处理常用命令大全
1.Echo 命令打开回显或关闭请求回显功能,或显示消息.如果没有任何参数,echo 命令将显示当前回显设置.语法echo [{on|off}] [message]Sample: echo off e ...
- Django基础之安装配置
安装配置 一 MVC和MTV模式 著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层:他们之间以一种插件似的,松耦合的方式连接在一起. 模型负责业务对象与数据库的 ...
- SpringMVC(四) RequestMapping请求方式
常见的Rest API的Get和POST的测试参考代码如下,其中web.xml和Springmvc的配置文件参考HelloWorld测试代码中的配置. 控制类的代码如下: package com.ti ...
- [LeetCode] Counting Bits 计数位
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the ...
- Cocos2dx 3.12 在AndroidStudio上编译配置
转载请标明出处:http://www.cnblogs.com/studweijun/p/5805576.html SDK,NDK,ANT的配置请看这里http://www.cnblogs.com/st ...
- .NET WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作)
好吧,还是那个社区APP,非管理系统,用户行为日志感觉不是很必要的,但是,错误日志咱还是得记录则个.总不能上线后报bug了让自己手足无措吧,虽然不管有木有错误日志报bug都是件很头疼的事... 我们知 ...
- jQuery之回调对象
1. jQuery 1.7 版本中新增的 jQuery.Callbacks() 函数返回一个全能的对象,此对象对管理回调列表提供了强大的方式.它能够增加.删除.触发.禁用回调函数. 2. callba ...
- ActiveMQ与spring集成实现Queue模式
ActiveMQ可以和spring很好的集成,下面我们来看看,如何做个集成的demo. (1)pom.xml引入相关jar <!-- spring相关 begin --> <depe ...