《C和指针》笔记(十四)-- 经典抽象数据类型

C/C++ 笔记

QQ : 1841545843
邮箱 : jiaxx903@163.com

一. 堆栈

/*
** 堆栈模拟接口
*/

#define STACK_TYPE int

// push
void push(STACK_TYPE value);

// pop
void pop(void);

// top
STACK_TYPE top(void);

// is_empty
int is_empty(void);

// is_full
int is_full (void);
/*
1. 在判断两个浮点数a, b是否相等时不要用a == b, 应该判断二者只差fabs(a-b)是否小于某个阈值
2. 判断一个整数位奇数,用 x % 2 != 0  x % 2 == 1(x有可能是负数)

 * 程序必须为同时处于活动状态的每个文件声明一个指针变量, 类型为FIFO*
 * 流通过调用fopen函数打开
 * 根据需要对文件进行读取与写入
 * 调用fclose关闭流
 */

 /*************************************************************/
 // 链表实现堆栈,在链表的起始位置操作
 
 #include "stack.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include <assert.h>
 
 #define FALSE 0
 
 // 定义一个结构以存储堆栈元素
 typedef struct STACK_NODE
 {
	 STACK_TYPE value;
	 struct STACK_NODE* next;
 } StackNode;
 
 // 指向堆栈中第一个节点的指针
 static StackNode* stack;
 
 // create_stack
 void create_stack(size_t size)
 {
 }
 
 // destroy_stack
 void destry_stack(void)
 {
	 while(!is_empty())
	 {
		 pop();
	 }
 }
 
 // push
 void push(STACK_TYPE value)
 {
	 StackNode* = new_node;
	 
	 new_node = malloc(sizeof(StackNode));
	 assert(new_node != NULL);
	 new_node->value = value;
	 new_node->next = stack;        // stack 永远指着第一个节点
	 stack = new_node;
}

// pop
void pop(void)
{
	StackNode* first_node;
	
	assert(!is_empty);
	first_node = stack;
	stack = first_node->next;
	free(first_node);
}

// top
STACK_TYPE top(void)
{
	assert(!is_empty());
	return stack->value;
}

// is_empty
int is_empty(void)
{
	return stack == NULL;
}

// is_full
int is_full(void)
{
	return FALSE;
}

二. 队列

 /*************************************************************/
 // 使用环数组实现队列
 
 // 环数组实现 : 当尾部下标超出数组尾部时把它设置为0
 rear += 1;
 if (rear >= QUEUE_SIZE)
 {
	 rear = 0;
 }
 // 另一种
 rear = (rear + 1) % QUEUE_SIZE;
 
 // 使用完全填满的策略来实现数组满和空的判断
 // 数组为空
 (rear + 1 ) % QUEUE_SIZE == front;
 
 // 数组为满
 (rear + 2 ) % QUEUE_SIZE == front;
 
 #include "deque.h"
 #include <stdio.h>
 #include <assert.h>
 
 #define QUEUE_SIZE 100               // 队列中元素的最大数
 #define ARRAY_SIZE (QUEUE_SIZE + 1)  // 数组的长度

// 用于存储队列元素的数组和指向队列头和尾的指针
static QUEUE_TYPE queue[ARRAY_SIZE];
static size_t front = 1;   // 头部
static size_t rear = 0;    // 尾部

// insert 
void insert (QUEUE_TYPE value)
{
	asset(!is_full());
	rear = (rear + 1) % ARRAY_SIZE;
	queue[rear] = value;
}

// delete
void delete(void)
{
	assert(!is_empty());
	front = (front + 1 ) % ARRAY_SIZE;
}

// first
QUEUE_TYPE first(void)
{
	assert(!is_empty());
	return queue[front];
}	

// is_empty
int is_empty(void)
{
	return (rear + 1) % ARRAY_SIZE == front;
}

// is_full
int is_full(void)
{
	return (rear + 2) % ARRAY_SIZE == front;
}

三.二叉搜索树

/****************************************************/
//
/*
** 1. 二叉搜索树中插入
**    如果树为空:
		 把新值作为根节点插入
	  否则:
		如果新值小于当前节点
			把新值插入当前节点的左子树
		否则:
			把新值插入当前节点的右子树
			
	2. 删除节点
		没有孩子的节点
		只有一个孩子的节点
		有两个孩子的节点
		
	3. 查找
	
	4. 树的遍历
		前序(pre-order)
		中序(in-order)
		后序(post-order)
		层次(breadth-first)
		
		
	
	
*/
/// 二叉搜索树接口
// tree.h

#define TREE_TYPE int  // 树的值类型

// insert 
void insert(TREE_TYPE value);

// find
TREE_TYPE* find(TREE_TYPE value);

// pre-order-traverse
// 执行树的先序遍历,它的参数是一个回调函数指针,
// 它所指向的函数将处理树中每个节点被调用,
// 节点的值作为参数传递给这个函数u
void pre_order_traverse(void (*callback)(TREE_TYPE));


/// /// 
// 使用静态数组实现二叉搜索树
// 数组长度通过#define来定义
#include“tree.h”
#include <assert.h>
#include <stdio.h>

#define TREE_SIZE 100 
#define ARRAY_SIZE (TREE_SIZE + 1)

// 用于存储所有节点的数组
static TREE_TYPE tree[ARRAY_SIZE];

// left_child
// 计算一个节点左孩子的下标
static int left_child(int current)
{
	return current * 2;
}

// right_child
// 计算一个节点右孩子的下标
static int right_child(int current)
{
	return current * 2 + 1;
}

// insert 
void insert (TREE_TYPE value)
{
	int current;
	
	// 确保值为非0, 0用来表示一个未使用的节点
	assert(value != 0);
	
	// 从根节点开始
	current = 1;
	
	// 从合适的子树开始,直到到达一个叶节点
	while (tree[current] != 0)
	{
		// 根据情况进入叶节点或右子树
		if (value < tree[current])
			current = left_child(current);
		else
		{		
			assert(value != tree[current]);
			current = right_child(current);
		}		
		
		assert(current < ARRAY_SIZE);
	}
	
	tree[current] = value;
}

// find
TREE_TYPE* find(TREE_TYPE value)
{
	int currnt;
	
	// 从根节点开始,直到找到那个值,进入合适的子树
	current = 1;
	
	while (currnt < ARRAY_SIZE &&tree[current] != value)
	{
		// 根据情况进入到右子树或左子树
		if (value < tree[currnt])
			current = left_child(current);
		else
			currnt = right_child(current);
		
	}
	
	if (current < ARRAY_SIZE)
		return tree + current;
	else
		return 0;
}

// 前序遍历
static void do_pre_order_travers(
	int current,
	void (*callback)(TREE_TYPE value)
	)
	{
		if (current < ARRAY_SIZE && tree[current] != 0)
		{
			callback(tree[current]);
			do_pre_order_travers(left_child(current), callback);
			do_pre_order_travers(right_child(current), callback);
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值