一、队列
1.1队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特性。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
2、顺序队列
代码
#include "seqqueue.h"
#include <stdio.h>
#include <string.h>
SeqQueue *CreateSeqQueue(int len)
{
SeqQueue* sq = malloc(sizeof(SeqQueue));
if(NULL ==sq)
{
perror("createseq que malloc");
return NULL;
}
sq->ptr= malloc(sizeof(DATATYPE)*len);
if(NULL == sq->ptr)
{
perror("create seqque malloc2");
return NULL;
}
sq->tlen = len;
sq->head = 0 ;
sq->tail = 0;
return sq;
}
int DestroySeqQueue(SeqQueue *queue)
{
free(queue->ptr);
free(queue);
return 0;
}
int QuitSeqQueue(SeqQueue *queue)
{
if(IsEmptySeqQueue(queue))
{
return 1;
}
queue->head = (queue->head+1)%queue->tlen;
return 0;
}
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{
if(IsFullSeqQueue(queue))
{
return 1;
}
memcpy(&queue->ptr[queue->tail],data,sizeof(DATATYPE));
queue->tail = (queue->tail+1)%queue->tlen;
return 0;
}
int IsEmptySeqQueue(SeqQueue *queue)
{
return queue->head == queue->tail;
}
int IsFullSeqQueue(SeqQueue *queue)
{
return queue->head == (queue->tail+1)%queue->tlen;
}
DATATYPE* GetHeadSeqQueue(SeqQueue*queue)
{
if(IsEmptySeqQueue(queue))
{
return NULL;
}
return &queue->ptr[queue->head];
}
头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
typedef int DATATYPE;
typedef struct queue {
DATATYPE *ptr;
int tlen;
int head;
int tail;
}SeqQueue;
SeqQueue *CreateSeqQueue(int len);
int DestroySeqQueue(SeqQueue *queue);
int QuitSeqQueue(SeqQueue *queue);
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data);
int IsEmptySeqQueue(SeqQueue *queue);
int IsFullSeqQueue(SeqQueue *queue);
DATATYPE* GetHeadSeqQueue(SeqQueue*queue);
#endif
3、多线程模型及队列的链
练习:
头文件:
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
typedef struct
{
char path[512];
}
DATATYPE;
typedef struct node {
DATATYPE data;
struct node *next;
}QueueNode;
typedef struct queue {
QueueNode *head;
int clen;
QueueNode *tail;
}LinkQueue;
LinkQueue *CreateLinkQueue();
int DestroyLinkQueue(LinkQueue *queue);
int QuitLinkQueue(LinkQueue *queue);
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
int IsEmptyLinkQueue(LinkQueue *queue);
DATATYPE* GetHeadLinkQueue(LinkQueue* que);
int GetSizeLinkQueue(LinkQueue*que);
#endif
队列的链
#include "linkque.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
LinkQueue *CreateLinkQueue()
{
LinkQueue* lq = malloc(sizeof(LinkQueue));
if(NULL == lq)
{
perror("createlinkque error");
return NULL;
}
lq->head= NULL;
lq->tail=NULL;
lq->clen=0;
return lq;
}
int DestroyLinkQueue(LinkQueue *queue)
{
int len = GetSizeLinkQueue(queue);
int i = 0 ;
for(i = 0 ;i<len;i++)
{
QuitLinkQueue(queue);
}
free(queue);
return 0;
}
int QuitLinkQueue(LinkQueue *queue)
{
if(IsEmptyLinkQueue(queue))
{
return 1;
}
QueueNode* tmp = queue->head;
queue->head = queue->head->next;
if(NULL ==queue->head)
{
queue->tail= NULL;
}
free(tmp);
queue->clen--;
return 0;
}
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{
QueueNode* newnode = malloc(sizeof(QueueNode));
if(NULL == newnode)
{
perror("enterqueue error");
return 1;
}
memcpy(&newnode->data,data,sizeof(DATATYPE));
newnode->next= NULL;
if(IsEmptyLinkQueue(queue))
{
queue->head = newnode;
queue->tail= newnode;
}
else
{
queue->tail->next = newnode;
queue->tail = newnode;
}
queue->clen++;
return 0;
}
int IsEmptyLinkQueue(LinkQueue *queue)
{
return 0 == queue->clen;
}
DATATYPE* GetHeadLinkQueue(LinkQueue* que)
{
if(IsEmptyLinkQueue(que))
{
return NULL;
}
return &que->head->data;
}
int GetSizeLinkQueue(LinkQueue*que)
{
return que->clen;
}
核心代码:
#include <stdio.h>
#include <stdlib.h>
#include "linkque.h"
#include <dirent.h>
#include <pthread.h>
#include <semaphore.h>
pthread_t main_th;
sem_t sem_task;
pthread_mutex_t mutex;
void do_ls(const char * path,LinkQueue*que,FILE* dstfp)
{
DIR * dir = opendir(path);
if(NULL == dir)
{
fprintf(stderr,"opendir errpr\n");
return ;
}
DATATYPE data;
while(1)
{
struct dirent * info = readdir(dir);
if(NULL == info)
{
break;
}
bzero(&data,sizeof(data));
char newpath[512]={0};
sprintf(newpath,"%s/%s",path,info->d_name);
printf("%s\n",newpath);
if(DT_DIR == info->d_type)// /home/linun/1.h
{
if(info->d_name[0]=='.')
{
continue;
}
// do_ls(newpath,sl);
// enterqueue():
if(pthread_self() == main_th)
{
strcpy(data.path,newpath);
pthread_mutex_lock(&mutex);
EnterLinkQueue(que,&data);
pthread_mutex_unlock(&mutex);
sem_post(&sem_task);
}
else
{
do_ls(newpath,que,dstfp);
}
}
else
{
if(strlen(newpath)<3
|| 0!=strcmp(&newpath[strlen(newpath)-2],".h"))
{
continue;
}
FILE* fp = fopen(newpath,"r");
if(NULL == fp)
{
perror("fopen");
return ;
}
int num =1;
while(1)
{
char buf[512]={0};
if(NULL == fgets(buf,sizeof(buf),fp))
{
break;
}
if(strstr(buf,"struct"))
{
fprintf(dstfp,"%d %s %s",num,newpath,buf);
}
num++;
}
fclose(fp);
}
}
closedir(dir);
}
typedef struct
{
FILE* fp;
LinkQueue*lq;
}TH_ARG;
void* th(void* arg)
{
TH_ARG* tmp = (TH_ARG*)arg;
DATATYPE* ret_head;
DATATYPE data;
while(1)
{
sem_wait(&sem_task);
pthread_mutex_lock(&mutex);
ret_head = GetHeadLinkQueue(tmp->lq);
memcpy(&data,ret_head,sizeof(DATATYPE));
QuitLinkQueue(tmp->lq);
pthread_mutex_unlock(&mutex);
if(0 == strcmp(data.path,"over"))
{
break;
}
do_ls(data.path , tmp->lq,tmp->fp);
}
return NULL;
}
int main(int argc, char **argv)
{
main_th = pthread_self();
LinkQueue* lq = CreateLinkQueue();
FILE* fp =fopen("log","w");
TH_ARG arg ;
arg.fp = fp;
arg.lq = lq;
pthread_t tid1,tid2,tid3;
sem_init(&sem_task,0,0);
pthread_mutex_init(&mutex,NULL);
pthread_create(&tid1,NULL,th,&arg);
pthread_create(&tid2,NULL,th,&arg);
pthread_create(&tid3,NULL,th,&arg);
do_ls("/home/linux/linux-4.15",lq,fp);
int i = 0 ;
for(i=0;i<3;i++)
{
DATATYPE data;
strcpy(data.path,"over");
pthread_mutex_lock(&mutex);
EnterLinkQueue(lq,&data);
pthread_mutex_unlock(&mutex);
sem_post(&sem_task);
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_join(tid3,NULL);
pthread_mutex_destroy(&mutex);
sem_destroy(&sem_task);
fclose(fp);
DestroyLinkQueue(lq);
printf("hello\n");
return 0;
}
二、树
1、定义
树是n(n>=0)个结点的有限集
当n=0时称为空树
树 其实也是一种递归的实现,即树的定义之中还用到了树的概念
2、特点
(1)且仅有一个特定的结点:根结点(Root)
(2)当 n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、T3......Tm
其中每一个集合本身又是一棵树,并且称为根的 子树(SubTree)
结点拥有子树的个数称谓结点的度。度为0的结点称谓叶结点。度不为0,称谓分支结点。
树的度数是指,这棵树中,最大的结点的度数,称谓树的度数。
树的深度或高度,从根开始,根为第一层,根的孩子为第二层。
下图所示的结构就不符合树的定义,因为它们都有相交的子树:
3、二叉树
二叉树,binary tree
n个结点的有限集合,集合要么为空树,要么由一个根结点和两棵互不相交,分别称谓根结点的左子树和右子树的二叉树组成。。
特点,
1,每个结点最多两个子树。
2,左子树和右子树是有顺序的,次序不能颠倒。
3,如果某个结点只有一个子树,也要区分左,右子树。
4、特殊的二叉树
特殊的二叉树
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;
4,有n个结点的完全二叉树深度为(logn/log 2) +1;
5、二叉树的四种遍历方式
1. 前序遍历
规则是先访问根结点
然后前序遍历左子树
再前序遍历右子树
(总结:根结点 -> 左子树 -> 右子树)
如下图所示,遍历的顺序为:ABDGHCEIF
2. 中序遍历
从根结点开始(注意并不是先访问根结点)
中序遍历根结点的左子树
然后再访问根结点
最后中序遍历右子树
(总结:左子树 -> 根结点 -> 右子树)
如下图所示,遍历的顺序为:GDHBAEICF
3.后序遍历
从左到右先叶子
后结点的方式遍历访问左右子树
最后访问根结点
(总结:**从左到右访问叶子结点 -> 根结点)
如下图所示,遍历的顺序为:GHDBIEFCA
4.层序遍历
从树的第一层,即根结点开始访问
从上而下逐层遍历
在同一层中按从左到右的顺序对结点逐个访问
(总结:第一层 -> 第二层(从左到右访问结点)-> ··· -> 最后一层(从左到右访问结点)
如下图所示,遍历的顺序为:ABCDEFGHI
6、代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char DATATYPE;
typedef struct BiTNode /* 结点结构 */
{
DATATYPE data; /* 结点数据 */
struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode;
char data[]="abd##eg###cf#h###";
int inx;
void CreateBiTree(BiTNode** root)
{
char c = data[inx++];
if('#'==c)
{
*root= NULL;
return ;
}
else
{
*root =(BiTNode*)malloc(sizeof(BiTNode));
if(NULL == *root)
{
return ;
}
(*root)->data = c;
CreateBiTree(&(*root)->lchild);
CreateBiTree(&(*root)->rchild);
}
return ;
}
void DestroyBiTree(BiTNode* root)
{
if(NULL == root)
{
return ;
}
DestroyBiTree(root->lchild);
DestroyBiTree(root->rchild);
free(root);
return ;
}
void PreOrderTraverse(BiTNode * root)
{
if(NULL == root)
{
return ;
}
printf("%c",root->data);
PreOrderTraverse(root->lchild);
PreOrderTraverse(root->rchild);
}
void InOrderTraverse(BiTNode* root)
{
if(NULL == root)
{
return ;
}
InOrderTraverse(root->lchild);
printf("%c",root->data);
InOrderTraverse(root->rchild);
}
void PostOrderTraverse(BiTNode*root)
{
if(NULL == root)
{
return ;
}
PostOrderTraverse(root->lchild);
PostOrderTraverse(root->rchild);
printf("%c",root->data);
}
int main(int argc, char *argv[])
{
BiTNode* root=NULL;
CreateBiTree(&root);
PreOrderTraverse(root);
printf("\n");
InOrderTraverse(root);
printf("\n");
PostOrderTraverse(root);
printf("\n");
DestroyBiTree(root);
return 0;
}