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
运行:


浙公网安备 33010602011771号