数据结构 队列、树

一、队列

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;
}

三、哈夫曼编码

四、哈希表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值