Recommend索引

<think>我们将实现随机推荐功能,包括根据不同的条件(如餐型、菜系、口味等)随机推荐菜谱。 此外,我们还会实现一个功能:根据喜好者推荐他们喜欢的菜。 注意:由于随机推荐需要从符合条件的菜谱中随机选择,我们将使用链表遍历和随机数生成。 文件:random_recommend.c 内容:包含随机推荐菜谱的函数实现</think>以下提供`random_recommend.c`文件的完整实现代码,包含菜谱随机推荐功能的详细实现。这个模块实现了根据多种条件随机推荐菜谱的功能,包括基于餐型、菜系、口味等条件的推荐,以及基于喜好者的个性化推荐。 ```c /* random_recommend.c - 随机推荐功能实现 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "random_recommend.h" #include "recipe_struct.h" #include "utils.h" // 初始化随机数生成器 void init_random() { static int initialized = 0; if (!initialized) { srand(time(NULL)); initialized = 1; } } // 获取随机菜谱 Recipe* get_random_recipe(RecipeNode* head) { if (head == NULL) return NULL; init_random(); // 计算链表长度 int count = 0; RecipeNode* current = head; while (current != NULL) { count++; current = current->next; } // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; for (int i = 0; i < random_index && current != NULL; i++) { current = current->next; } return (current != NULL) ? &(current->recipe) : NULL; } // 按餐型推荐 Recipe* recommend_by_meal_type(RecipeNode* head, MealType meal_type) { if (head == NULL) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { if (current->recipe.meal_type == meal_type) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { if (current->recipe.meal_type == meal_type) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 按菜系推荐 Recipe* recommend_by_cuisine(RecipeNode* head, CuisineType cuisine) { if (head == NULL) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { if (current->recipe.cuisine == cuisine) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { if (current->recipe.cuisine == cuisine) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 按口味推荐 Recipe* recommend_by_flavors(RecipeNode* head, int flavors) { if (head == NULL) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { // 检查是否包含所有请求的口味 if ((current->recipe.flavors & flavors) == flavors) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { if ((current->recipe.flavors & flavors) == flavors) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 按状态推荐 Recipe* recommend_by_textures(RecipeNode* head, int textures) { if (head == NULL) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { // 检查是否包含所有请求的状态 if ((current->recipe.textures & textures) == textures) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { if ((current->recipe.textures & textures) == textures) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 按喜好者推荐 Recipe* recommend_by_lover(RecipeNode* head, const char* lover_name) { if (head == NULL || lover_name == NULL || *lover_name == &#39;\0&#39;) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { // 检查喜好者字符串中是否包含指定名称 if (strstr(current->recipe.lovers, lover_name) != NULL) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { if (strstr(current->recipe.lovers, lover_name) != NULL) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 综合推荐 Recipe* comprehensive_recommend(RecipeNode* head, MealType meal_type, CuisineType cuisine, int flavors, int textures, const char* lover_name) { if (head == NULL) return NULL; init_random(); // 计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { int match = 1; // 检查餐型 if (meal_type != -1 && current->recipe.meal_type != meal_type) { match = 0; } // 检查菜系 if (match && cuisine != -1 && current->recipe.cuisine != cuisine) { match = 0; } // 检查口味 if (match && flavors != 0 && (current->recipe.flavors & flavors) != flavors) { match = 0; } // 检查状态 if (match && textures != 0 && (current->recipe.textures & textures) != textures) { match = 0; } // 检查喜好者 if (match && lover_name != NULL && *lover_name != &#39;\0&#39; && strstr(current->recipe.lovers, lover_name) == NULL) { match = 0; } if (match) { count++; } current = current->next; } if (count == 0) return NULL; // 生成随机索引 int random_index = rand() % count; // 找到对应节点 current = head; int found = 0; while (current != NULL) { int match = 1; if (meal_type != -1 && current->recipe.meal_type != meal_type) { match = 0; } if (match && cuisine != -1 && current->recipe.cuisine != cuisine) { match = 0; } if (match && flavors != 0 && (current->recipe.flavors & flavors) != flavors) { match = 0; } if (match && textures != 0 && (current->recipe.textures & textures) != textures) { match = 0; } if (match && lover_name != NULL && *lover_name != &#39;\0&#39; && strstr(current->recipe.lovers, lover_name) == NULL) { match = 0; } if (match) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } return NULL; } // 随机推荐菜单 void random_recommend_menu(RecipeNode* recipe_head, LoverNode* lover_head) { int choice; do { printf("\n=== 随机推荐 ===\n"); printf("1. 完全随机推荐\n"); printf("2. 按餐型推荐\n"); printf("3. 按菜系推荐\n"); printf("4. 按口味推荐\n"); printf("5. 按状态推荐\n"); printf("6. 按喜好者推荐\n"); printf("7. 综合条件推荐\n"); printf("0. 返回主菜单\n"); choice = get_int_input("请选择推荐方式: "); if (choice == -1 || choice == 0) break; Recipe* recommended = NULL; switch (choice) { case 1: // 完全随机 recommended = get_random_recipe(recipe_head); break; case 2: { // 按餐型 MealType meal_type = get_meal_type(); if (meal_type == -1) break; recommended = recommend_by_meal_type(recipe_head, meal_type); break; } case 3: { // 按菜系 CuisineType cuisine = get_cuisine_type(); if (cuisine == -1) break; recommended = recommend_by_cuisine(recipe_head, cuisine); break; } case 4: { // 按口味 int flavors = get_flavors(); if (flavors == 0) { printf("未选择任何口味!\n"); break; } recommended = recommend_by_flavors(recipe_head, flavors); break; } case 5: { // 按状态 int textures = get_textures(); if (textures == 0) { printf("未选择任何状态!\n"); break; } recommended = recommend_by_textures(recipe_head, textures); break; } case 6: { // 按喜好者 char lover_name[100]; if (lover_head == NULL) { printf("喜好者列表为空!\n"); break; } // 显示所有喜好者 print_all_lovers(lover_head); get_string_input("输入喜好者姓名: ", lover_name, sizeof(lover_name)); if (lover_name[0] == &#39;\0&#39;) break; recommended = recommend_by_lover(recipe_head, lover_name); break; } case 7: { // 综合条件 MealType meal_type = -1; CuisineType cuisine = -1; int flavors = 0; int textures = 0; char lover_name[100] = {0}; // 收集条件 if (yes_no_prompt("是否指定餐型?")) { meal_type = get_meal_type(); } if (yes_no_prompt("是否指定菜系?")) { cuisine = get_cuisine_type(); } if (yes_no_prompt("是否指定口味?")) { flavors = get_flavors(); } if (yes_no_prompt("是否指定状态?")) { textures = get_textures(); } if (lover_head != NULL && yes_no_prompt("是否指定喜好者?")) { print_all_lovers(lover_head); get_string_input("输入喜好者姓名: ", lover_name, sizeof(lover_name)); } recommended = comprehensive_recommend(recipe_head, meal_type, cuisine, flavors, textures, lover_name); break; } default: printf("无效选择!\n"); } // 显示推荐结果 if (recommended != NULL) { printf("\n=== 为您推荐 ===\n"); print_recipe_details(recommended); } else { printf("\n没有找到符合条件的菜谱!\n"); } // 继续推荐 if (choice != 0 && !yes_no_prompt("是否继续推荐?")) { break; } } while (choice != 0); } ``` ### 功能详细说明 #### 1. 随机数初始化 - **函数**:`init_random()` - **功能**:使用当前时间初始化随机数生成器 - **特点**: - 使用静态变量确保只初始化一次 - 避免重复推荐相同序列 #### 2. 基础推荐功能 1. **完全随机推荐**: - 从所有菜谱中随机选择 - 实现:`get_random_recipe()` 2. **按餐型推荐**: - 随机选择指定餐型的菜谱 - 实现:`recommend_by_meal_type()` 3. **按菜系推荐**: - 随机选择指定菜系的菜谱 - 实现:`recommend_by_cuisine()` 4. **按口味推荐**: - 随机选择包含所有指定口味的菜谱 - 使用位掩码技术高效匹配 - 实现:`recommend_by_flavors()` 5. **按状态推荐**: - 随机选择包含所有指定状态的菜谱 - 使用位掩码技术高效匹配 - 实现:`recommend_by_textures()` 6. **按喜好者推荐**: - 随机选择指定喜好者喜欢的菜谱 - 使用字符串匹配查找喜好者 - 实现:`recommend_by_lover()` #### 3. 高级推荐功能 - **综合推荐**:`comprehensive_recommend()` - 支持多条件组合: - 餐型 - 菜系 - 口味 - 状态 - 喜好者 - 条件可选(使用特殊值表示忽略) - 所有条件使用AND逻辑组合 #### 4. 用户交互菜单 - **功能**:`random_recommend_menu()` - **特点**: - 7种推荐方式选择 - 交互式条件输入 - 结果即时显示 - 支持连续推荐 - 自动处理空结果 ### 算法实现细节 1. **两阶段随机选择**: ```c // 第一阶段:计算符合条件的菜谱数量 int count = 0; RecipeNode* current = head; while (current != NULL) { if (/* 匹配条件 */) { count++; } current = current->next; } // 第二阶段:随机选择 if (count > 0) { int random_index = rand() % count; current = head; int found = 0; while (current != NULL) { if (/* 匹配条件 */) { if (found == random_index) { return &(current->recipe); } found++; } current = current->next; } } ``` 2. **位掩码匹配**: ```c // 检查是否包含所有指定口味 if ((current->recipe.flavors & flavors) == flavors) { // 匹配成功 } ``` 3. **字符串部分匹配**: ```c // 检查喜好者是否包含指定名称 if (strstr(current->recipe.lovers, lover_name) != NULL) { // 匹配成功 } ``` 4. **条件组合处理**: ```c int match = 1; // 餐型检查 if (meal_type != -1 && current->recipe.meal_type != meal_type) { match = 0; } // 菜系检查 if (match && cuisine != -1 && current->recipe.cuisine != cuisine) { match = 0; } // 其他条件检查... if (match) { // 符合所有条件 } ``` ### 关键设计特点 1. **高效随机算法**: - O(n)时间复杂度完成随机选择 - 只需遍历链表两次(计数+选择) - 内存使用恒定(O(1)额外空间) 2. **灵活的条件处理**: - 使用特殊值(-1, 0, NULL)表示忽略条件 - 位掩码实现高效多值匹配 - 支持任意条件组合 3. **健壮的错误处理**: - 空链表检测 - 无效输入处理 - 无匹配结果处理 - 边界条件检查 4. **用户友好交互**: - 清晰的菜单导航 - 分步条件输入 - 结果格式化显示 - 连续操作支持 ### 使用示例 ```text === 随机推荐 === 1. 完全随机推荐 2. 按餐型推荐 3. 按菜系推荐 4. 按口味推荐 5. 按状态推荐 6. 按喜好者推荐 7. 综合条件推荐 0. 返回主菜单 请选择推荐方式: 7 是否指定餐型?(y/n): y 餐型选择: 1.早餐 2.正餐 3.甜品 4.零食 5.饮品 请选择餐型(1-5): 2 是否指定菜系?(y/n): y 菜系选择: 1.鲁菜 2.川菜 3.粤菜 4.苏菜 5.闽菜 6.浙菜 7.湘菜 8.徽菜 9.东北菜 10.家常菜 11.西餐 请选择菜系(1-11): 2 是否指定口味?(y/n): y 口味选择(多选,输入0结束): 1.酸 2.甜 3.苦 4.辣 5.咸 6.凉 7.热 选择口味(1-7, 0结束): 1 选择口味(1-7, 0结束): 4 选择口味(1-7, 0结束): 0 是否指定状态?(y/n): n 是否指定喜好者?(y/n): y === 喜好者列表 === 1. 张三 2. 李四 3. 王五 输入喜好者姓名: 李四 === 为您推荐 === ========== 菜谱详情 ========== ID: 1001 菜名: 鱼香肉丝 餐型: 正餐 口味: 酸,辣 状态: 软 菜系: 川菜 食材: 猪肉;木耳;胡萝卜;青椒 步骤: 切丝;腌制;炒制;调味 时间: 30分钟 喜好者: 张三;李四 ============================== 是否继续推荐?(y/n): n ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值