相较稳定的红包算法实现/c语言实现

2023-11-11

红包的分配分布,个人认为能够运用到正态分布是极好,运气好的人少,运气差的人也少,但是本篇算法并不打算利用正态分布的特性来实现分配红包算法(本人太菜),而是一个产生红包相对稳定,一定程度上也算一个是符合正太分布特性的算法(世间很多事物的分布一定程度上都满足正态分布,我的理解:1、总量是固定不变的(具体特性记不得了),;2、分布呈现的是两边少,中间多;)。

下面介绍以下该算法的思路中涉及比较重要的点

    1. 随机二分法(我自己取的名字,大概的意思就是使用一个随机数,将一个较大的值随机分为两个较小的值)。

    2. 每次将集合(分割出来的节点)中值最大的节点进行分割。

 算法涉及的基本数据结构介绍:

    1. Node,红包节点,属性(金额,相邻的前后红包节点指针)

    2. List,链表,属性(红包总数,红包总金额,指向最大金额红包的head指针,和指向金额最小的tail指针)

算法流程:

    1. 首先初始化链表(红包总金额和总数),并向链表中插入总金额的红包节点; 

    2. 取出最大的红包节点,将其金额进行分割,将分割的金额生成两个红包节点;

    3. 将分割出来的红包节点插入链表中;

    4. 执行2, 3过程,直至分割出预期的红包个数

    ... todo, 可以通过遍历链表获取从大到小排序的红包节点。可以按照规则实现(获取大额红包的人尽可能是比较快的人,等等),将节点有规则或者无规则的打乱然后放入到队列中,抢红包的时候就从队列中取出即可。

 

以下是算法的源码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>

const float MIN = 0.01;
const float MIN_LIMIT_PERCENT = 0.5;
const float ROUND_FLOAT = 0.005;

/*----------- 涉及到的数据结构的定义*/
/*=======Node */
typedef struct Node{
    float val;          //值
    struct Node * pre;
    struct Node * next;
} nod;

nod * create_node(float value)
{
    nod * node = (nod *)malloc(sizeof(nod));
    node->val = value;
    node->pre = NULL;
    node->next = NULL;
    return node;
}

void rep_node(nod * before, nod * cur)
{
    cur->next = before->next;
    cur->pre = before;
    before->next->pre = cur;
    before->next = cur;
}

/*=======list */
typedef struct List{
    nod * tail;    //链表尾部
    nod * head;    //链表头部
    int number;     //结点数量
    float value;    //链表总值
} LT;

void init_lt(LT * l, float value, int number)
{
    l->tail = NULL;
    l->head = NULL;
    l->number = number;
    l->value = value;
}

nod * get_head(LT * l)
{
    return l->head;
}

nod * pop(LT * l)
{
    nod * node = l->head;
    if(!node)
    {
        return node;
    }
    nod * n_head = node->next;
    node->next = NULL;
    l->head = n_head;
    if(!l->head)
    {
        l->tail = NULL;
    }
    return node;
}

void inst_node(LT * l, nod * node)
{
    nod * head = l->head;
    if(!head)
    {
        l->head = node;
        l->tail = node;
        return;
    }
    nod * before;
    nod * go = head;
    while(go && go->val > node->val)
    {
        before = go;
        go = go->next;
    }
    if(!go)
    {
        before->next = node;
        l->tail = node;
    }
    else
    {
        //链表头节点置换
        if(go == head)
        {
            node->next = head;
            l->head = node;
        }
        else
        {
            rep_node(before, node);
        }
    }
    return;
}


/*----------- 涉及到的算法*/
float random(int mask)
{
    int random = rand();
    //printf("random:%d, mask:%d, div:%d, mid:%0.4f\n", random, mask, (random%mask+1), (float)(random%mask+1)/(mask+2));
    return (float)((int)((((float)(random%mask+1)/(mask+2))+0.0005)*1000))/1000;
}

//分割一个数
float divide(float value, float percent)
{
    //printf("percent:%f\n", percent);
    return (float)((int)((value*percent+ROUND_FLOAT)*100))/100;
}

/*----------- process*/
void work(LT * l, float money, int count)
{
    srand(time(NULL));
    nod * mey = create_node(money);
    inst_node(l, mey);
    int mask = count-1;
    //将money分割count次
    while(count-- > 0)
    {
        //将最大节点弹出
        nod * max_value_node = pop(l);
        //printf("node:%0.2f, count:%d\n", max_value_node->val, count);
        //产生一个随机数, 随机切分最大节点的值c,产生两个数a、b, c = a+b;
        //float div_left = divide(max_value_node->val, random(count+1));    //波动幅度较下面的小
        float div_left = divide(max_value_node->val, random(mask));         //波动幅度较上面的大
        //当数值及其小时,采取对分的方法,将value分割开来
        if(div_left - 0 < MIN || max_value_node->val - div_left < MIN)
        {
            div_left = (float)((int)(((max_value_node->val*MIN_LIMIT_PERCENT)+ROUND_FLOAT)*100))/100;
        }
        float div_right = max_value_node->val - div_left;
        //生成两个节点a, b;
        nod * left_nod = create_node(div_left);
        nod * right_nod = create_node(div_right);
        //printf("left:%0.2f, right:%0.2f\n", div_left, div_right);
        //依次插入链表中
        inst_node(l, left_nod);
        inst_node(l, right_nod);
        free(max_value_node);
    }
    printf("============= result =============\n");
    _print(l);
}


/*----------- test*/
void _print(LT * l)
{
    nod * go = l->head;
    int count = 0;
    float sum = 0.00;
    while(go)
    {
        count++;
        sum += go->val;
        printf("node->value:%0.3f\n", go->val);
        go = go->next;
    }
    printf("sum:%0.2f, count:%d", sum, count);
}

/*----------- main*/
int main()
{
    float money = 100.00;        //红包总金额
    int number = 100;            //红包个数
    if(money/number - MIN < 0) {
        return 0;
    }
    //创建一个链表
    LT * l = (LT *)malloc(sizeof(LT));
    init_lt(l, money, number);
    //printf("number:%d, value:%0.2f\n", l->number, l->value);
    work(l, money, number-1);
    return 0;
}

 

算法改进:上面算法用到的数据结构是链式的,时间复杂度为O(n^2),如果将堆作为算法的底层结构,那么时间复杂度会降低为O(nlogn),之后我会写一篇新的文章来讲解优化后的算法。优化算法链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

相较稳定的红包算法实现/c语言实现 的相关文章

  • 用741运算放大器搭建RC正弦振荡器:文氏电桥振荡电路

    实验目的 了解正弦振荡器的工作原理 加强仿真multisim软件的运用水平 加强对电路的理解 搭建电路的动手能力 了解个元器件之间的配合 实验电路原理图 左侧为仿真电路 右侧为振荡波形 电路原理及其分析 I RC正弦波振荡电路又称文氏电桥振

随机推荐

  • linux性能分析工具专题-perf(事件采样,全面性能分析)

    文章目录 概述 perf概念 perf的工具集合介绍 perf的事件介绍 perf list参看 常用perf性能查看工具使用 perf stat 运行一个命令并且统计过程事件 perf top 输出系统某个事件热度函数或者指令排序 per
  • ArcGIS Pro python 获取一百多幅栅格的平均值

    目标 我需要计算流域内的平均等效水柱高 等效水柱高的格网已经创建好 如下 每个月一个这样的栅格格网 现在有近两百个格网需要求平均等效水柱高 要求 按照时间顺序求取每一个格网的平均等效水柱高 并生成时间序列表单 如下 看到arcpro上显示栅
  • 有空就看看的leetcode1——两数之和(c++版)

    有空就看看的leetcode1 两数之和 c 版 学习前言 两数之和题目 几个需要用到的函数 解法 1 遍历法 2 哈希表法 学习前言 有点紧张 决定看看leetcode 两数之和题目 给定一个整数数组 nums 和一个目标值 target
  • 多线程进阶(上)

    目录 一 常见的锁策略 二 CAS 三 synchronized的优化 一 常见的锁策略 1 乐观锁和悲观锁 乐观锁 从名字上来看就可以看出来 这个很乐观 这个会预期锁冲突的概率很低 就会认为锁即将要被解除了 不需要等待很久 因此上 乐观锁
  • postgresql数据库linux centos7 安装

    简介 百度百科 PostgreSQL是一种特性非常齐全的自由软件的对象 关系型数据库管理系统 ORDBMS 是以加州大学计算机系开发的POSTGRES 4 2版本为基础的对象关系型数据库管理系统 POSTGRES的许多领先概念只是在比较迟的
  • Flink RocketMQ Connector实现

    Flink内置了很多Connector 可以满足大部分场景 但是还是有一些场景无法满足 比如RocketMQ 需要消费RocketMQ的消息 需要自定时Source 一 自定义FlinkRocketMQConsumer 参考FlinkKaf
  • 使用Nginx反向代理Vue项目时,报Invalid Host header错误解决办法

    在vue config js中 修改配置 disableHostCheck true module exports devServer open true host batman com port 27202 https false dis
  • 数据结构之KMP算法

    一 首先求next值 例如 模式串 a b a a b c a c next值 0 1 1 2 2 3 1 2 next数组的求解方法是 第一位的next值为0 第二位的next值为1 后面求解每一位的next值时 根据前一位进行比较 首先
  • 一文让你明了P NP NPC 问题

    这或许是众多OIer最大的误区之一 你会经常看到网上出现 这怎么做 这不是NP问题吗 这个只有搜了 这已经被证明是NP问题了 之类的话 你要知道 大多数人此时所说的NP问题其实都是指的NPC问题 他们没有搞清楚NP问题和NPC问题的概念 N
  • 第14.2节 HTML知识简介

    一 HTML语言 HTML 指的是超文本标记语言 Hyper Text Markup Language 它不是一种编程语言 而是一种使用一套标记标签 markup tag 来标记元素作用的标记语言 标记语言使用标记标签来描述网页的内容 标记
  • 如何在linux中打印程序堆栈信息

    如何在linux中打印程序堆栈信息 用于调试 有时候在写完代码之后需要自己手动测试功能 在linux环境中往往需要gdb调试打断点查看堆栈 往往公司的服务器一般是多人同时使用的 往往性能不是太强 gdb调试的时候载入的时候Reading s
  • Java 中 try-catch,throw和throws的使用

    Java 中的异常有很多 这种异常机制 可以帮助处理程序中未知的错误 关于异常的处理有try catch 程序块 throw throws 以下分别对这三种进行介绍 一 try catch try catch用来捕获代码段的异常并做出处理
  • SQL语句知识大全

    目录导航 一 SQL简介 1 什么是数据库 2 数据库分类 3 SQL 是什么 4 SQL 能做什么 5 RDBMS 二 基础语法 1 创建数据库 2 删除数据库 3 创建表 4 删除新表 5 增加一个列 6 添加主键 7 创建索引 8 创
  • python实现物体定位

    前段时间利用实验室的器材写了一个小小的项目 简单的整理了一下 并不完善 现在分享一下 实验的内容是 使用卫星定位信息接收器 接收物体的位置信息 包括经度纬度等等 然后解析这些数据 然后根据经度纬度等信息通关百度地图API获取物体的具体位置信
  • 分享常用JDBC连接参数

    oracle 驱动 oracle jdbc driver OracleDriver URL jdbc oracle thin
  • 依靠自我

    必读网 http www beduu com 整理 依靠自我 我们需要爱默生式的思想家 当所有的编译工作都完成之后 我突然发现自己在编译过程中经常出现的 为什么要编译爱默生的文章 的疑问都变得多余了 也就是说 我突然认为 在中国重提爱默生是
  • iOS:如何在iphone、ipad上安装一些常用命令行命令

    iOS 如何在iphone ipad上安装一些常用命令行命令 相信对Linux Unix比较熟悉的朋友 在iphone或 ipad越狱后发现通过Cydia可以安装OpenSSH 一定都想安装上并且通过ssh登录上去看看 但是登录后却发现几乎
  • jsch jar包连接不上ssh报Algorithm negotiation fail 错误

    参考 JSchException Algorithm negotiation fail问题解决之路 GreatQing的个人页面 OSCHINA 中文开源技术交流社区 1 jsch jar包连接不上ssh报Algorithm negotia
  • python 报错error193_WindowsError:[错误193]%1不是在Python有效的Win32应用程序

    I wish to import liblas module in Python 2 7 on window 64bit If I import the module with IDLE Python GUI I have no probl
  • 相较稳定的红包算法实现/c语言实现

    红包的分配分布 个人认为能够运用到正态分布是极好 运气好的人少 运气差的人也少 但是本篇算法并不打算利用正态分布的特性来实现分配红包算法 本人太菜 而是一个产生红包相对稳定 一定程度上也算一个是符合正太分布特性的算法 世间很多事物的分布一定