多线程排序-v22

makefile

v22:v22.o
	gcc -o v22 v22.o -lm -lpthread
v22.o:v22.c
	gcc -c v22.c
.PHONY:clean
clean:
	-rm v22
	-rm *.o
	-rm *.txt

v22.c

// 多线程排序-v22
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>


#define SIZE 16

// 原始数据结构体
struct data_size
{
    int size;
    int *data;
};

struct data_info
{
    int size;
    int *data;
};

struct thread_data
{
    struct data_size array;     // 选择处理哪一块的数组
    struct data_info *bins;
    pthread_t tid;
};


// 初始化原始数据
int *allocate(int size) // 错误:struct data_size array,正确:需要申请内存空间的大小
{
    int *space;
    space = (int *)calloc(size, sizeof(int));   // 强制类型转换,内存的大小,每个单元的数据类型
    // 防止申请内存失败
    if (space == NULL)
    {
        perror("Error allocate.");
        exit(EXIT_FAILURE);
    }
    return space;
}

// 生成随机数据
void produce_data(struct data_size array)
{
    srand(1);
    for (int i = 0; i < array.size; i++)
    {
        array.data[i] = rand() % 1000;
    }
}


// 打印数据
void print_data(struct data_size array, char * txt)
{
    FILE * fp;
    //char num_str[4] = {0};        // 错误
    // char num_str[4] = {'\0'};   // 方法1
    // char num_str[4] = '\0';     // 方法2
    // char num_str[4] "";         // 方法3
    char num_str[4];                // 方法4
    memset(num_str, 0, sizeof(num_str));

    fp = fopen(txt, "w");
    if (fp == NULL)
    {
        perror("Error fopen.");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < array.size; i++)
    {
        sprintf(num_str, "%d", array.data[i]); // int sprintf(char *str, const char *format, ...)
        // size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
        fwrite(num_str, sizeof(num_str), 1, fp);
        fputc('\n', fp);
    }

    fclose(fp);
}

// 划分数据
void split_data(struct data_size array, struct data_info bins[])   // 参数是一个未指定大小的数组
{
    for (int i = 0; i < array.size; i++)
    {
        int number = array.data[i];
        
        if (number < 250)
        {
            bins[0].data[bins[0].size++] = number;
        }
        else if (number < 500)
        {
            bins[1].data[bins[1].size++] = number;
        }
        else if (number < 750)
        {
            bins[2].data[bins[2].size++] = number;
        }
        else
        {
            bins[3].data[bins[3].size++] = number;
        }
    }
}


// 排序
void *insertion(void *params)
{
    struct thread_data args = *(struct thread_data *)params;
    struct data_info bin = *args.bins;

    for (int i = 1; i < bin.size; i++)
    {
        for (int j = i; j > 0; j--)
        {
            if (bin.data[j - 1] > bin.data[j])
            {
                int temp;
                temp = bin.data[j];
                bin.data[j] = bin.data[j - 1];
                bin.data[j - 1] = temp;
            }
            else
            {
                break;
            }
        }
    }
}

// 数据从缓存区到原始数据区
void move_data(struct data_size array, struct data_info bins[])
{
    for (int bin = 0; bin < 4; bin++)
    {
        for (int i = 0; i < bins[bin].size; i++)
        {
            *array.data++ = bins[bin].data[i];
        }
    }
}


// 检查排序是否正确
bool is_sorted(struct data_size array)
{
    bool sorted = true;
    for (int i = 0; i < array.size - 1; i++)    // 这里需要下表减一
    {
        if (array.data[i] > array.data[i+1])
        {
            sorted = false;
            return sorted;
        }
    }
    return sorted;
}

int main(int argc, char *argv[])
{
    // 初始化参数
    struct data_size array;
    struct data_info bins[4];       // 为什么是4个数组?
    struct thread_data threads[4];

    // 设置参数量
    if (argc < 2)
    {
        array.size = SIZE;
    }
    else
    {
        array.size = pow(2, atoi(argv[1]));
    }

    // 分配数据集空间
    array.data = allocate(array.size);
    for (int i  = 0; i < 4; i++)
    {
        bins[i].size = 0;
        bins[i].data = allocate(array.size);    // 每个现成的的缓存空间都是元数据的大小,资源不浪费嘛
    }

    // 初始化原始数据
    array.data = allocate(array.size);
    produce_data(array);
    print_data(array, "original.txt");

    // 划分数据
    split_data(array, bins);

    // 计算缓存区数据量
    int sum = 0;
    for (int i = 0; i < 4; i++)
    {
        sum += bins[i].size;
    }
    printf("Size is:%d.\n", sum);

    // 创建多线程,执行排序任务
    for (int i = 0; i < 4; i++)
    {
        threads[i].bins = &bins[i];         // threads的bins的地址和bins的地址保持一致
        if (pthread_create(&threads[i].tid, NULL, insertion, (void *)&threads[i]))  // 参数传参的方式
        {
            perror("Error pthread_create.\n");
            exit(EXIT_FAILURE);
        }
    }

    // 多线程同步
    for (int i = 0; i < 4; i++)
    {
        pthread_join(threads[i].tid, NULL);
    }

    // 打印数据
    move_data(array, bins);
    print_data(array, "insertion.txt");
    printf(is_sorted(array) ? "sorted\n" : "not sorted\n");

    // 释放内存空间
    free(array.data);
    for (int i = 0; i < 4; i++)
    {
        free(bins[i].data);
    }

    exit(EXIT_SUCCESS);
}
posted @ 2022-07-08 16:41  starc的miao  阅读(49)  评论(0)    收藏  举报