2015年阿里研发工程师实习笔试附加题

本文探讨了内存池管理和线程安全实现,提出一种固定大小内存块管理方案,并设计了一个根据用户配额分配资源的队列类。此外,还提供了一个解决RPC请求乱序问题的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目1:

常常会有频繁申请、释放内存的需求,比如在发送网络报文时,每次都要分配内存以存储报文,等报文发送完成后又需要删除报文。
为了避免频繁的new/delete对系统带来的开销,需要实现一个通用的FreeList机制。使用者总是从free list中分配内存,如果存在没有使用的内存块就直接摘出来使用,如果没有的话再从系统中分配。使用完毕后并不去直接delete该内存块,而是交给FreeList保管。
要求:

  1. 实现一个对固定大小内存块进行管理的通用FreeList类,给出定义和实现。要求不能使用STL中的容器类。定义类的接口和实现时注意通用性、健壮性和可测试性。
  2. 如果该类的对象可能会被多个thread同时访问,请描述如何怎样保证线程安全。有没有办法在保证线程安全的同时尽可能增大并发度?如果有也请描述你的思路。
#include <bits/stdc++.h>
#include <Windows.h>
//#include <afxmt.h>
using namespace std;
const int N = 32;
template<typename T>
class MemoryPool {
public:
    MemoryPool() { Expand(); };
    MemoryPool(size_t cnt) {
        Expand();
    }
    ~MemoryPool() {
        MemoryPool<T> *pNext = nullptr;
        for (pNext = FreeList; pNext != nullptr;pNext=FreeList) {
            FreeList = FreeList->FreeList;
            delete[](char*)pNext;
        }
    }
    void *Alloc() {
        if (FreeList == nullptr) 
            Expand();
        MemoryPool<T>* p = nullptr;
        p = FreeList;
        FreeList = FreeList->FreeList;
        return p;
    }
    void Free(void *p){
        MemoryPool<T> *tmp = nullptr;
        tmp = static_cast<MemoryPool<T>*>(p);
        tmp->FreeList = FreeList;
        FreeList = tmp;
    }
    void Expand(int cnt = N) {
        size_t size = max(sizeof(T) , sizeof(MemoryPool<T>*));
        MemoryPool<T> *LastItem = static_cast<MemoryPool<T>*>(static_cast<void *>(new char[size]));
        FreeList = LastItem;
        for (int i = 0; i < cnt; i++) {
            LastItem->FreeList = static_cast<MemoryPool<T>*>(static_cast<void *>(new char[size]));
            LastItem = LastItem->FreeList;
        }
        LastItem->FreeList = nullptr;
    }
    MemoryPool<T> *FreeList;
};
class CriticalSection{
public:
    CriticalSection() {
        InitializeCriticalSection(&cs);
    }
    ~CriticalSection() {
        DeleteCriticalSection(&cs);
    }
    void Lock() {
        EnterCriticalSection(&cs);
    }
    void Unlock() {
        LeaveCriticalSection(&cs);
    }
    CRITICAL_SECTION cs;
};
template<typename T,typename L>
class MTMemoryPool {
public:
    MTMemoryPool() {};
    void *Alloc() {
        void *p = nullptr;
        lock.Lock();
        p = pool.Alloc();
        lock.Unlock();
        return p;
    }
    void Free(void *p) {
        lock.Lock();
        pool.Free(p);
        lock.Unlock();
    }
    T pool;
    L lock;
};
class Node {
public:
    static void *inew() {
        void *p = s_pool->Alloc();
        return p;
    }
    static void idelete(void *p) {
        s_pool->Free(p);
    }
    static void NewPool() {
        s_pool = new MTMemoryPool<MemoryPool<Node>, CriticalSection>;
    }
    static void DeletePool() {
        delete s_pool;
        s_pool = nullptr;
    }
    static MTMemoryPool<MemoryPool<Node>, CriticalSection> *s_pool;
};
MTMemoryPool<MemoryPool<Node>, CriticalSection> *Node::s_pool = nullptr;
void fun() {
    Node *test[100005];
    for (int i = 0; i <= 100000; i++) {
        test[i] = new Node;
    }
    for (int i = 0; i <= 100000; i++) {
        delete test[i];
    }
}
void ifun() {
    Node *test[100005];
    for (int i = 0; i <= 100000; i++) {
        test[i]=(Node*)Node::inew();
    }
    for (int i = 0; i <= 100000; i++) {
        Node::idelete(test[i]);
    }
}
int main() {
    int start = clock();
    fun();
    printf("%d\n", clock() - start); //GetTickCount();
    start = clock();
    Node::NewPool();
    ifun();
    Node::DeletePool();
    printf("%d\n", clock() - start);
    return 0;
}

可能由于只用一个线程什么的,用了临界区等,反而时间慢了一倍。。。

题目2:

假设这样一个场景:当很多用户并发获取服务,server端资源不足时,希望用户能够按照预先分配的配额来使用资源。
比如预先定义好user1, user2, user3的配额是20%, 30%, 50%,资源争抢时希望服务器有20%的服务能力分配给user1, 30%给user2, 50%给user3。
但是如果某个时刻只有user1的请求,server还是要把100%的服务能力分配给user1以充分利用资源;又如某个时间段只有user2/user3在访问服务,则按照30%:50%的比率来分配资源。

需要通过一个类似于队列的ManagedQueue类来封装上述功能。
入队的时候需要提供user id(32位正整数)以及用户的任务(Task)。我们假设系统的用户数是有上限的,不会超过10个。

当队列中各个用户的请求均非空时,要求出队的task分布符合用户的配额设置。延续上面的例子如果连续出队100次,要求user1的task有20个左右,user2的task 30个左右, user3的50个左右。

这里出队的task恰好能对应服务器的服务能力。

要求:

  1. 给出关键数据结构以及ManagedQueue的定义。用户任务Task可以认为是一个已经实现的类来使用。可以使用STL容器类。
  2. 实现出队方法Dequeue(),请尽可能写健壮的代码
    注意:这里并不要求精确的按照比例分配任务,只要统计意义上满足预定义的配额比例就可以了。
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
struct ManagedQueue {
    int id;
    int data;
};
deque<ManagedQueue> dq;

struct Node {
    bool flag;
    int cnt;
};
void fun(int x) {

}
void test(vector<int> v,int cnt) {
    vector<ManagedQueue>g;
    vector<Node>c;
    while (!dq.empty()) {
        c.clear(); g.clear();
        for (int i = 0; i < v.size(); i++)
            c.push_back(Node{ 0,0 });
        for (int i = 0; i < cnt; i++) {
            g.push_back(dq.front());
            c[dq.front().id].flag = true;
            dq.pop_front();
        }
        int total = 0;
        for (int i = 0; i < v.size(); i++) {
            if (c[i].flag) {
                total += v[i];
            }
        }
        for (int i = 0; i < v.size(); i++) {
            if (c[i].flag) {
                c[i].cnt = max(1,cnt*v[i] / total);
            }
        }
        for (int i = 0; i < cnt; i++) {
            if (c[g[i].id].cnt > 0) {
                fun(g[i].data);
                c[g[i].id].cnt--;
            }
            else {
                dq.push_front(g[i]);
            }
        }
    }
}
int main() {
    //init dq;
    vector<int> v = { 2,3,5 };
    int cnt=100;
    test(v,cnt);
    return 0;
}

题目3:

分布式系统中的RPC请求经常出现乱序的情况。
写一个算法来将一个乱序的序列保序输出。例如,假设起始序号是1,对于(1, 2, 5, 8, 10, 4, 3, 6, 9, 7)这个序列,输出是:
1
2
3, 4, 5
6
7, 8, 9, 10

上述例子中,3到来的时候会发现4,5已经在了。因此将已经满足顺序的整个序列(3, 4, 5)输出为一行。

要求:

  1. 写一个高效的算法完成上述功能,实现要尽可能的健壮、易于维护
  2. 为该算法设计并实现单元测试
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
int a[N];
int vis[N];
int main() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    int j = 1;
    for (int i = 1; i <= n; i++) {
        vis[a[i]] = 1;
        if (a[i] == j) {
            while (vis[j]) {
                printf("%d ", j);
                j++;
            }
            printf("\n");
        }
    }
    return 0;
}

不知道对不

转载于:https://www.cnblogs.com/HaibaraAi/p/4401130.html

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值