【学习记录】AVL树及相关链表,线程池实现

本来打算使用avl树套链表的结构,来避免优先级相等的情况,但是最后发现当绝大多数优先级都相等,avl树还是不可避免的退化成单链表,而需求中也确实是绝大多数都是优先级相等。

所以评估之后觉得avl树带来的提升远不及其提升的复杂度,所以放弃该方案,改为链表实现,现将此前实验的代码整理如下,

AVL树部分应该没有问题。重要步骤做了注释

.c文件如下

c 复制代码
//
// Created by Administrator on 2025/2/10.
//
#ifdef __cplusplus
extern "C" {
#endif
#include "threadpool.h"
#include <malloc.h>
#include <pthread.h>
#include "string.h"
///---------------------------链表操作----------------

/**
 * @brief 比较两个节点的数据
 * @param 数据1
 * @param 数据2
 * @return 0-相等 -1-不相等
 * */
int compare_node(Task_t target1,Task_t target2){
    return (target1.func == target2.func)&&(strncmp(target1.task_name,target2.task_name,strlen(target2.task_name))==0)&&(target1.priority == target2.priority);
}

//在尾巴插入一个节点
int list_insert_r(AVLData * list_head,AVLData new_node){
    if (list_head == NULL) return 0;
//    if (new_node == NULL) return 0; //新建数据节点必须在之前分配好内存
    AVLData * newnode = (AVLData *)malloc(sizeof(AVLData));
    if(newnode == NULL){
        return -1; //内存开辟失败
    }
    (*newnode)=new_node;
    AVLData * p= list_head;
    //设置新节点数据
    newnode->next = NULL;
    newnode->key=newnode->task.priority;
    while (p->next){//第一个节点不存数据
        p=p->next;
    }
    p->next = newnode;
    return 0;
}
/**
 * @brief 删除节点,对比任务名,任务优先级和任务函数指针,全部一样删除
 * @param list_head 链表头
 * @param del_node 要删除的节点
 * @return 0-删除成功 -1-删除失败
 * */
int list_node_del(AVLData * list_head,Task_t del_node){
    AVLData * p = list_head;
    while (p->next){//
        if(compare_node(p->next->task,del_node)==0){ //如果相等
            break;
        }
        p = p->next;
    }
    if(p->next == NULL )
        return -1; //未找到
    AVLData * q = p->next;
    p->next = p->next->next;
    free(q);
    return 0;
}
/**
 * @brief 遍历节点
 * @param list_head 链表首元结点
 * */
int list_traverse(AVLData * list_head){
    AVLData * p = list_head;
    p=p->next;
    while (p){
        printf("节点数据\n");
        p=p->next;
    }
    return 0;
}




///---------------------------AVL树----------------
// 获取节点高度
int get_avltree_height(AVLNode *node) {
    if (node == NULL) return 0;
    return node->height;
}

// 新建节点
AVLNode* avltree_newNode(AVLData data) {
    AVLNode* node = (AVLNode*) malloc(sizeof(AVLNode));
    if(node == NULL){
        _exit(-1);//申请内存失败
    }
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    node->height = 1; // 新节点初始高度设为1
    return node;
}

// 右旋
AVLNode *rightRotate(AVLNode *y) {
    AVLNode *x = y->left;
    AVLNode *T2 = x->right;

    x->right = y; //自身插入原来自己左孩子的右节点 完成右旋
    y->left = T2; //冲突的右孩变左孩

    y->height = 1 + (get_avltree_height(y->left) > get_avltree_height(y->right) ? get_avltree_height(y->left) : get_avltree_height(y->right));
    x->height = 1 + (get_avltree_height(x->left) > get_avltree_height(x->right) ? get_avltree_height(x->left) : get_avltree_height(x->right));

    return x;
}

// 左旋
AVLNode *leftRotate(AVLNode *x) {
    AVLNode *y = x->right;
    AVLNode *T2 = y->left;

    y->left = x; //原来节点变成其右孩子的左孩子 完成左旋
    x->right = T2; //冲突左孩变右孩

    //重新计算高度 左右孩子中最高的+自身
    x->height = 1 + (get_avltree_height(x->left) > get_avltree_height(x->right) ? get_avltree_height(x->left) : get_avltree_height(x->right));
    y->height = 1 + (get_avltree_height(y->left) > get_avltree_height(y->right) ? get_avltree_height(y->left) : get_avltree_height(y->right));

    return y;
}

// 获取平衡因子
int getBalanceFactor(AVLNode *N) {
    if (N == NULL) return 0;
    return get_avltree_height(N->left) - get_avltree_height(N->right);
}

// 插入节点
AVLNode* avltree_insert(AVLNode* node, AVLData data) {
    if (node == NULL)
        return avltree_newNode(data);

    if (data.key < node->data.key) //小的靠左
        node->left  = avltree_insert(node->left, data);
    else if (data.key > node->data.key)
        node->right = avltree_insert(node->right, data);
    else{//相同节点这个需要在进行处理,考虑在该节点处增加链表存储相同优先级的
        list_insert_r(&node->data,data); //在当前节点的数据链表后插入
        return node;
    }


    node->height = 1 + (get_avltree_height(node->left) > get_avltree_height(node->right) ? get_avltree_height(node->left) : get_avltree_height(node->right));

    int balance = getBalanceFactor(node);

    if (balance > 1 && data.key < node->left->data.key) // LL型 右旋
        return rightRotate(node);
    if (balance < -1 && data.key > node->right->data.key) // RR型 左旋
        return leftRotate(node);
    if (balance > 1 && data.key > node->left->data.key) { //LR型 左旋左孩子 然后右旋
        node->left =  leftRotate(node->left);
        return rightRotate(node);
    }
    if (balance < -1 && data.key < node->right->data.key) { //RL型 右旋右孩子 然后左旋
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    return node;
}

// 查找最小值节点
AVLNode * minValueNode(AVLNode* node) {
    AVLNode* current = node;
    while (current->left != NULL)
        current = current->left;
    return current;
}

// 删除节点
AVLNode* avltree_deleteNode(AVLNode* root, AVLData data) {
    if (root == NULL)
        return root;

    if ( data.key < root->data.key )
        root->left = avltree_deleteNode(root->left, data);
    else if( data.key > root->data.key )
        root->right = avltree_deleteNode(root->right, data);
    else { //等于的情况
        if((root->left == NULL) || (root->right == NULL)) { //如果是叶子节点
            AVLNode *temp = root->left ? root->left : root->right;

            if (temp == NULL) { //没有子树
                temp = root;
                root = NULL; //如果是叶子节点 直接删除 这一步在返回时会赋值给上一层的 root->left 或者  root->right
            } else //有一个子树
                *root = *temp; // 单边为空 复制非空子项的内容 然后将节点删除
            free(temp);
        } else { //两边都不为空 两个子树
            AVLNode* temp = minValueNode(root->right);//找到后驱节点 右边最接近删除节点的值
            root->data = temp->data;  //只替换值 保留左右子树和高度信息

            root->right = avltree_deleteNode(root->right, temp->data); //将后驱节点删除,此时后驱节点必然是只有一个子树或者没有子树,坍缩为之前两种情况
        }
    }

    if (root == NULL)
        return root;

    root->height = 1 + (get_avltree_height(root->left) > get_avltree_height(root->right) ? get_avltree_height(root->left) : get_avltree_height(root->right));

    int balance = getBalanceFactor(root);

    if (balance > 1 && getBalanceFactor(root->left) >= 0) //LL
        return rightRotate(root);

    if (balance > 1 && getBalanceFactor(root->left) < 0) { //LR
        root->left = leftRotate(root->left);
        return rightRotate(root);
    }

    if (balance < -1 && getBalanceFactor(root->right) <= 0) //RR
        return leftRotate(root);

    if (balance < -1 && getBalanceFactor(root->right) > 0) {//RL
        root->right = rightRotate(root->right);
        return leftRotate(root);
    }

    return root;
}

// 中序遍历打印
void inorderTraversal(AVLNode *root) {
    if(root != NULL) {
        inorderTraversal(root->left);
        printf("%d ", root->data.key);
        inorderTraversal(root->right);
    }
}

/// ------------------------------线程池操作------------------------------------








void* thread_worker(void *arg) {
    Thread_pool_t *pool = (Thread_pool_t*)arg;
    while (1) {
        pthread_mutex_lock(&pool->lock);

//        // 调整队列中的任务优先级
//        adjust_priority(pool->task_queue, pool->queue_start, pool->queue_end, pool->queue_size);
//
//        while (pool->queue_count == 0 && !pool->shutdown) {
//            pthread_cond_wait(&pool->cond, &pool->lock);
//        }
//        if (pool->shutdown) {
//            pthread_mutex_unlock(&pool->lock);
//            pthread_exit(NULL);
//        }
//
//        task_t *task = pool->task_queue[pool->queue_start];
//        if (task->exec_count > 0 && difftime(time(NULL), task->last_exec_time) >= task->interval) {
//            pool->queue_start = (pool->queue_start + 1) % pool->queue_size;
//            pool->queue_count--;
//
//            task->func(task->arg); // 执行任务
//            task->last_exec_time = time(NULL);
//            if (--task->exec_count > 0) {
//                insert_task_by_priority(pool->task_queue, task, &pool->queue_start, &pool->queue_end, &pool->queue_count, pool->queue_size);
//            } else {
//                free(task);
//            }
//        } else {
//            pthread_mutex_unlock(&pool->lock);
//            continue;
//        }
        pthread_mutex_unlock(&pool->lock);
    }
    return NULL;
}




Thread_pool_t* thread_pool_init(int num_workers, int queue_size) {
    Thread_pool_t *pool = (Thread_pool_t *)malloc(sizeof(Thread_pool_t));
    if (pool == NULL) return NULL;

    pool->num_workers = num_workers;
    pool->queue_size = queue_size;
    pool->workers = (pthread_t *)malloc(num_workers * sizeof(pthread_t));
    pool->task_queue = (Task_t**)malloc(queue_size * sizeof(Task_t*));
    pool->queue_start = 0;
    pool->queue_end = 0;
    pool->queue_count = 0;
    pool->shutdown = 0;

    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->cond, NULL);

    for (int i = 0; i < num_workers; ++i) {
        if (pthread_create(&pool->workers[i], NULL, thread_worker, pool) != 0) {
            fprintf(stderr, "线程创建失败\n");
            _exit(-1);
        }
    }

    return pool;
}

void insert_task_by_priority(Task_t **queue, Task_t *task, int *queue_start, int *queue_end, int *queue_count, int queue_size) {
    int pos = *queue_end;
    while (pos != *queue_start) {
        int prev_pos = (pos - 1 + queue_size) % queue_size;
        if (queue[prev_pos]->priority <= task->priority) break;
        queue[pos] = queue[prev_pos];
        pos = prev_pos;
    }
    queue[pos] = task;
    *queue_end = (*queue_end + 1) % queue_size;
    (*queue_count)++;
}


/**
 * @param pool 线程池
 * @param func 任务
 * @param arg 任务参数
 * @param priority 任务优先级
 * @param exec_count 任务循环次数
 * @param interval 任务执行间隔时间
 * */
int thread_pool_submit(Thread_pool_t *pool, task_func func, void *arg, int priority, int exec_count, int interval) {
    if (pool->queue_count == pool->queue_size) return -1;


    Task_t *task = (Task_t *)malloc(sizeof(Task_t));
    task->func = func;
    task->arg = arg;
    task->priority = priority;
    task->exec_count = exec_count;
    task->last_exec_time = time(NULL) - interval - 1; // 确保首次可以被执行
    task->interval = interval;

    pthread_mutex_lock(&pool->lock);
    insert_task_by_priority(pool->task_queue, task, &pool->queue_start, &pool->queue_end, &pool->queue_count, pool->queue_size);
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->lock);

    return 0;
}




#ifdef __cplusplus
}
#endif

.h文件如下

c 复制代码
//
// Created by Administrator on 2025/2/10.
//
#ifndef DEVP_THREADPOOL_H
#define DEVP_THREADPOOL_H

#ifdef __cplusplus
extern "C" {
#endif
#include <time.h>
#include <pthread.h>
#include <unistd.h>
typedef void (*task_func)(void*);
typedef struct {
    task_func func;             // 任务函数
    char task_name[128];        // 任务名称
    void* arg;                  // 任务参数
    int priority;               // 任务优先级
    int exec_count;             // 执行次数
    long int last_exec_time;    // 上次执行时间
    long int interval;          // 执行间隔时间(ms)
}Task_t;

// 线程池结构体
typedef struct {
    int num_workers;            //工作线程数
    pthread_t *workers;
    Task_t **task_queue;
    int queue_size;             //最大任务数
    int queue_start;
    int queue_end;
    int queue_count;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    int shutdown;                   //线程退出
}Thread_pool_t;


///------------------------------------AVL树相关------------------------------------------

typedef struct avldata{
    Task_t task; //保留一个首元结点不放数据
    struct avldata *next ; //这里做链表来存储 相同优先级的任务
    int key; //这里是key作为AVL树来排序的依据,默认和task内部的优先级相同,当然也可以绑定其它的数值
}AVLData;


// 定义AVL树节点
typedef struct AVLNode {
    AVLData data;
    struct AVLNode *left;
    struct AVLNode *right; //作为树时使用
//    struct AVLNode *next;  //作为链表时使用
    int height;
}AVLNode;




#ifdef __cplusplus
}
#endif


#endif //DEVP_THREADPOOL_H
相关推荐
虾球xz9 分钟前
游戏引擎学习第99天
javascript·学习·游戏引擎
练小杰1 小时前
【MySQL例题】我在广州学Mysql 系列——有关数据备份与还原的示例
android·数据库·经验分享·sql·学习·mysql
larry_dongy1 小时前
VMware Workstate 的 Ubuntu18 安装 vmware tools(不安装没法共享)
学习·ubuntu
菜鸟码农011 小时前
Datawhale 组队学习 wow-agent task1 学习总结
python·学习·datawhale
靡不有初1112 小时前
CCF-CSP第34次认证第二题——矩阵重塑(其二)【需反复思考学习!!!】
c++·学习·线性代数·矩阵·备考·ccfcsp
莲动渔舟3 小时前
pytest测试专题 - 1.1 运行pytest
笔记·学习·pytest
虾球xz3 小时前
游戏引擎学习第95天
人工智能·学习·游戏引擎
C182981825755 小时前
算法-反转链表
数据结构·链表
onlyzzr6 小时前
Leetcode Hot100 第18题 146.LRU缓存
算法·leetcode·链表