六:队列(一般做缓冲区,缓冲队列)
一:定义
队列是只允许在一段进行插入,而在另一端进行删除操作的线性表。允许插入的称谓队尾,允许删除的一端叫队头。
顺序队列。循环队列
常用操作,入队,出队。
先进先出,FIFO
typedef int DATATYPE;
typedef struct queue {
DATATYPE *array;
int tlen;
int head;
int tail;
}SeqQueue;
二:CreateSeqQueue
SeqQueue *CreateSeqQueue(int len)
{
SeqQueue* sq = malloc(sizeof(SeqQueue));
if(NULL == sq)
{
fprintf(stderr,"CreateSeqQueue malloc error\n");
return NULL;
}
sq->array = malloc(sizeof(DATATYPE)*len);
if(NULL == sq->array)
{
fprintf(stderr,"CreateSeqQueue malloc2 error\n");
return NULL;
}
sq->head = 0 ;
sq->tail = 0;
sq->tlen = len;
return sq;
}
三:EnterSeqQueue
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{
if(IsFullSeqQueue(queue))
{
printf("queue is full\n");
return 1;
}
memcpy(&queue->array[queue->tail],data,sizeof(DATATYPE));
queue->tail = (queue->tail+1)%queue->tlen;
return 0;
}
四:QuitSeqQueue
int QuitSeqQueue(SeqQueue *queue)
{
if(IsEmptySeqQueue(queue))
{
printf("queue is empty\n");
return 1;
}
queue->head = (queue->head+1)%queue->tlen;
return 0;
}
五:IsEmptySeqQueue/IsFullSeqQueue
int IsEmptySeqQueue(SeqQueue *queue)
{
return queue->head == queue->tail;//tail = head
}
int IsFullSeqQueue(SeqQueue *queue)
{
return (queue->tail +1)%queue->tlen == queue->head;//tail+1 = head
//代码的作用是更新队头指针head的位置,而取模运算%是为了实现循环队列(CircularQueue)的特性
}
六:GetHeadSeqQue
DATATYPE* GetHeadSeqQue(SeqQueue *queue)
{
if(IsEmptySeqQueue(queue))
{
return NULL;
}
return &queue->array[queue->head];
}
七:DestroySeqQueue
int DestroySeqQueue(SeqQueue *queue)
{
free(queue->array);
free(queue);
return 0;
}
七:树
一:定义
树:n(n>=0)个结点的有限集合。n = 0 ,空树。
在任意一个非空树中,
1,有且仅有一个特定的根结点
2,当n>1 时,其余结点可分为m个互不相交的有限集合T1,T2,T3.。。。。Tm,其中每一个集合又是一个树,并且称谓子树。
结点拥有子树的个数称谓结点的度。度为0的结点称谓叶结点。度不为0,称谓分支结点。
树的度数是指,这棵树中,最大的结点的度数,称谓树的度数。
树的深度或高度,从根开始,根为第一层,根的孩子为第二层。
树的存储:顺序结构,链式结构。
二:二叉树
二叉树,binary tree
n个结点的有限集合,集合要么为空树,要么由一个根结点和两棵互不相交,分别称谓根结点的左子树和右子树的二叉树组成。。
特点,
1,每个结点最多两个子树。
2,左子树和右子树是有顺序的,次序不能颠倒。
3,如果某个结点只有一个子树,也要区分左,右子树。
特殊的二叉树
1,斜树,所有的结点都只有左子树,左斜树,所有结点都只有右子树,右树。
2,满二叉树,所有的分支结点都存在左右子树,并且叶子都在同一层上。
3,完全二叉树,对于一颗有n个结点的二叉树按层序编号,如果编号i(1<=i<=n)的结点于同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这可树为完全二叉树。(从左往右,从上到下边,编号与满二叉树一模一样)
特性
1,在二叉树的第i
层上最多有2^(i-1)
个结点 i>=1
2,深度为k的二叉树至多有2^k -1
个结点 k>=1
3,任意一个二叉树T,如果其叶子结点的个数是n0
,度数为2的结点数为n2, n0 = n2 +1
;(度为2的结点个数+1)
4,有n个结点的完全二叉树深度为(logn/log 2) +1
;
三:遍历的三种
层序,(用的递归的写法)
前序,根左右,先访问根,然访问左,访问右。
中序,左根右,先从根开始(不是先访问根),从左开始访问,在访问根,在访问右结点。
后序,左右根,先从根开始(不是先访问根),先访问左,在访问右。在访问根。
四:二叉树基本调试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char DATATYPE;
typedef struct BiTNode
{
DATATYPE data;
struct BiTNode *lchild,*rchild;
}BitTNode;
char dat[] = "abd##eh###c#fi###";
int ind = 0;
void CreateTree(BitTNode ** root)//二重指针,用地址修改main函数
{
char c = dat[ind++];
if('#' == c)
{
*root = NULL;
}else
{
*root = malloc(sizeof(BitTNode));
if(NULL == *root)
{
printf("malloc errorn\n");
return;
}
(*root)->data = c;
CreateTree(&(*root)->lchild);
CreateTree(&(*root)->rchild);
}
return;
}
void PreOrderTraverse(BitTNode * root)
{
if(NULL == root)
{
return ;
}else
{
printf("%c",root->data);
PreOrderTraverse(root->lchild);
PreOrderTraverse(root->rchild);
}
}
int main(int argc, char **argv)
{
BitTNode * root = NULL;
CreateTree(&root);
PreOrderTraverse(root);
system("pause");
return 0;
}
一:tree
的gdb
调试
gcc -g main.c//生成a.out
gdb ./a.out //调试gdb
b CreatTree//在此函数设置断点
r //运行
display c //一直显示XX函数中 追踪的c的状态
n //向下一行运行
bt //显示目前程序已有数据赋值或者XX的具体状态
二:PreOrderTraverse
前序
/**
* @brief 根左右
*
* @param root
*/
void PreOrderTraverse(BiTNode*root)
{
if(NULL==root )
{
return ;
}
else
{
printf("%c",root->data);//root
PreOrderTraverse(root->lchild);// lift
PreOrderTraverse(root->rchild);// right
}
}
三:InOrderTraverse
中序
/**
* @brief 左根右
*
* @param root
*/
void InOrderTraverse(BiTNode* root)
{
if(NULL == root)
{
return ;
}
InOrderTraverse(root->lchild);
printf("%c",root->data);
InOrderTraverse(root->rchild);
}
四:PostOrderTraverse
后序
/**
* @brief 左右根
*
* @param root
*/
void PostOrderTraverse(BiTNode* root)
{
if(NULL == root)
{
return ;
}
PostOrderTraverse(root->lchild);
PostOrderTraverse(root->rchild);
printf("%c",root->data);
}
五:DestroyBiTree
销毁
void DestroyBiTree(BiTNode*root)
{
if(NULL ==root)
{
return ;
}
DestroyBiTree(root->lchild);
DestroyBiTree(root->rchild);
free(root);
}
六:逐层遍历二叉树(练习)
.h文件
typedef struct BiTNode* DATATYPE1; // 修改为存储二叉树节点指针
//这是最重要的,直接改为能放入二叉树,通过节点放入
typedef struct queue {
DATATYPE1 *array;
int tlen;
int head;
int tail;
}SeqQueue;
typedef char DATATYPE2;
typedef struct BiTNode /* 结点结构 */
{
DATATYPE2 data; /* 结点数据 */
struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode;
SeqQueue *CreateSeqQueue(int len);
int EnterSeqQueue(SeqQueue *queue, DATATYPE1 *data);
int QuitSeqQueue(SeqQueue *queue);
int IsEmptySeqQueue(SeqQueue *queue);
int IsFullSeqQueue(SeqQueue *queue);
DATATYPE1* GetHeadSeqQue(SeqQueue *queue);
int DestroySeqQueue(SeqQueue *queue);
void CreateTree(BiTNode **root);
void DestroyBiTree(BiTNode *root);
.c文件,此为修改部分,其他部分不变
int ind = 0;
void CreateTree(BiTNode **root)
{
char dat[] = "abd##eh###c#fi###";//二叉树元素
char c = dat[ind++];
if ('#' == c)
{
*root = NULL;
}
else
{
*root = malloc(sizeof(BiTNode));
if (NULL == *root)
{
printf("malloc error\n");
return;
}
(*root)->data = c;
CreateTree(&(*root)->lchild);
CreateTree(&(*root)->rchild);
}
return;
}
main函数
int main(int argc, char** argv)
{
BiTNode* root = NULL;
CreateTree(&root);
//char dat[] = "abd##eh###c#fi###";
SeqQueue* sq = CreateSeqQueue(20);
EnterSeqQueue(sq, &root);//把第一个根放进去(首根)
while (!IsEmptySeqQueue(sq))
{
BiTNode * tmp = *GetHeadSeqQue(sq);//获得队列的头元素
QuitSeqQueue(sq);
printf("%c ", tmp->data);
if(tmp->lchild != NULL)
{
EnterSeqQueue(sq,&tmp->lchild);
}
if(tmp->rchild != NULL)
{
EnterSeqQueue(sq,&tmp->rchild);
}
}
putchar('\n');
DestroySeqQueue(sq);
DestroyBiTree(root);
// system("pause");
return 0;
}//先全部放进去,然后拿出来比较二叉树元素