基于链表实现大数除法的C语言技术问题求助
解决大整数链表除法(减法模拟)的问题
首先,我得梳理下你代码里的几个核心问题,这些问题直接导致你得不到正确结果:
核心问题分析
1. 除法逻辑完全颠倒
你的division函数逻辑搞反了:
- 循环条件应该是被除数(oper1) >= 除数(oper2),而不是你写的
oper2->content >= oper1->content(这只比较了单个节点的字符,完全不代表整个数的大小) - 循环内应该是被除数减去除数,同时结果计数器(result)递增1,但你现在的代码是用result减去oper1,完全不符合减法模拟除法的逻辑。
2. 缺少大整数比较函数
你不能直接用单个节点的content来比较整个大整数的大小,必须实现一个函数来判断两个链表表示的大整数谁更大,或者是否相等。
3. 结构体命名不一致
你的increment函数参数用了t_bistro,但你定义的结构体是t_BigNumber,这是笔误,必须统一命名。
4. 链表操作的细节问题
你用lstadd把字符加到链表头部,导致链表是低位在前存储(比如"125"存储为5→2→1),这没问题,但所有运算函数(加法、减法、比较)都必须适配这个存储顺序。
修正步骤与代码实现
第一步:实现大整数比较函数
我们需要一个is_greater_or_equal函数,判断链表a(被除数)是否大于等于链表b(除数):
#include <string.h> // 比较两个低位在前的大整数:a >= b 返回1,否则返回0 int is_greater_or_equal(t_BigNumber *big, t_list *a, t_list *b) { // 先比较长度,更长的数更大 int len_a = 0, len_b = 0; t_list *tmp_a = a, *tmp_b = b; while (tmp_a) { len_a++; tmp_a = tmp_a->next; } while (tmp_b) { len_b++; tmp_b = tmp_b->next; } if (len_a != len_b) { return len_a > len_b ? 1 : 0; } // 长度相同,递归从高位到低位比较(链表尾部是高位) static int compare_same_length(t_BigNumber *big, t_list *a, t_list *b) { if (!a->next && !b->next) { // 最后一个节点(最高位) int idx_a = strchr(big->base, *(char*)a->content) - big->base; int idx_b = strchr(big->base, *(char*)b->content) - big->base; return idx_a >= idx_b; } // 先递归比较更高位 int higher = compare_same_length(big, a->next, b->next); if (higher != 0) { return higher; } // 高位相等,比较当前位 int idx_a = strchr(big->base, *(char*)a->content) - big->base; int idx_b = strchr(big->base, *(char*)b->content) - big->base; return idx_a >= idx_b; } return compare_same_length(big, a, b); }
第二步:修正除法函数的逻辑
现在把除法函数的逻辑改对:循环判断被除数是否大于等于除数,若是则被除数减去除数,结果计数器加1:
// 注意:oper1是被除数,oper2是除数,返回商(result) t_list *division(t_BigNumber *big, t_list *oper1, t_list *oper2) { t_list *result; t_list *tmp_oper1; // 初始化结果为0 result = NULL; lstadd(&result, ft_lstnew(&(big->base[0]), 1)); // 复制被除数,避免修改原链表 tmp_oper1 = copy_list(oper1); while (is_greater_or_equal(big, tmp_oper1, oper2)) { // 被除数减去除数 t_list *new_oper1 = subtract(big, tmp_oper1, oper2); del_num(tmp_oper1); tmp_oper1 = new_oper1; // 结果计数器加1 t_list *new_result = increment(big, result); del_num(result); result = new_result; } del_num(tmp_oper1); return result; }
第三步:修正increment函数的结构体命名
把t_bistro改成t_BigNumber,统一结构体命名:
t_list *increment(t_BigNumber *big, t_list *oper) { t_list *incr; t_list *counter; incr = NULL; // 创建值为1的链表节点(用于加法实现递增) lstadd(&incr, ft_lstnew(&(big->base[1]), 1)); counter = addition(big, oper, incr); del_num(oper); free(incr->content); free(incr); return counter; }
第四步:补充缺失的辅助函数
你需要实现几个关键辅助函数来完善功能:
copy_list:复制链表,避免修改原被除数
t_list *copy_list(t_list *src) { t_list *dest = NULL; t_list **last = &dest; while (src) { *last = ft_lstnew(src->content, src->content_size); src = src->next; last = &(*last)->next; } return dest; }
del_num:正确释放链表的每个节点和内容
void del_num(t_list *num) { t_list *tmp; while (num) { tmp = num; num = num->next; free(tmp->content); free(tmp); } }
ft_lstnew:确保正确分配内存并复制内容
#include <stdlib.h> #include <string.h> t_list *ft_lstnew(void const *content, size_t content_size) { t_list *new = malloc(sizeof(t_list)); if (!new) return NULL; if (content) { new->content = malloc(content_size); if (!new->content) { free(new); return NULL; } memcpy(new->content, content, content_size); } else { new->content = NULL; } new->content_size = content_size; new->next = NULL; return new; }
第五步:修正main函数的内存管理
确保所有分配的内存都被正确释放,避免泄漏:
#include <stdio.h> #include <stdlib.h> int main() { t_list *op1; // 被除数125 t_list *op2; // 除数5 t_list *result; t_BigNumber *big; char *str = "125"; char *str1 = "5"; op1 = NULL; op2 = NULL; // 构建被除数链表:低位在前 → 5→2→1 while (*str) { lstadd(&op1, ft_lstnew(str, 1)); str++; } // 构建除数链表:5 → 单个节点 while (*str1) { lstadd(&op2, ft_lstnew(str1, 1)); str1++; } big = malloc(sizeof(t_BigNumber)); if (!big) { del_num(op1); del_num(op2); return 1; } big->base = "0123456789"; big->base_size = 10; result = division(big, op1, op2); digitizer(result); // 输出25 printf("\n"); // 释放所有内存 del_num(op1); del_num(op2); del_num(result); free(big); return 0; }
关键注意事项
- 链表存储顺序:一定要确保所有运算函数(加法、减法、比较、递增)都适配低位在前的存储方式,否则会出现计算错误。
- 内存管理:大整数运算很容易出现内存泄漏,一定要记得释放所有分配的链表节点和结构体。
- 减法函数的正确性:你的
subtract函数必须正确处理低位在前的大整数减法,包括借位逻辑,否则除法的每一步都会出错。
现在,按照这个修正后的代码,你应该能得到正确的输出25了。
内容的提问来源于stack exchange,提问作者Zeid Tisnes
相关产品推荐
相关产品推荐

