使用链表计算两个大整数的和

使用链表计算两个大整数的和

一道有意思的编程练习题:

两个单链表(singly linked list),每一个节点里面一个0-9的数字,输入就相当于两个大数了。然后返回这两个数的和(一个新list)。这两个输入的list长度相等。 要求是:1. 不用递归。2. 要求算法在最好的情况下,只遍历两个list一次 ,最差的情况下两遍。

下面是我的解法:

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

#define MAX 32 // 列表长度

struct Node {
    char num;
    struct Node *next;
};

void list_build(struct Node **list);
void list_add(struct Node *list1, struct Node *list2, struct Node **sum);
void list_print(struct Node *list);
void list_free(struct Node *list);

int main(int argc, char *argv[])
{
    int i;
    struct Node *list1;
    struct Node *list2;
    struct Node *sum;

    // 随机函数初始化
    srand((unsigned int)time(NULL));

    for(i = 0; i < 100; i++) {
        // 将三个列表初始化为空
        list1 = list2 = sum = NULL;

        // 构建链表
        list_build(&list1);
        list_build(&list2);

        // 链表相加
        list_add(list1, list2, &sum);

        // 格式化输出
        list_print(list1); printf(" + ");
        list_print(list2); printf(" == ");
        list_print(sum);
        printf("\n");

        // 释放分配的heap空间
        list_free(list1);
        list_free(list2);
        list_free(sum);
    }

    system("pause"); 
    return 0;
}

// 头部插入一个元素
struct Node * insert(struct Node *list, struct Node *node)
{
    struct Node *swap;
    swap = list;
    list = node;
    list->next = swap;

    return list;
}

// 使用随机数生成一个链表
void list_build(struct Node **list)
{
    int i;
    struct Node *node;

    *list = NULL;

    for(i = 0; i < MAX; i++) {
        node = (struct Node *)malloc(sizeof(struct Node));

        node->num = rand() % 10;
        node->next = NULL;

        if(*list == NULL ) {
            *list = node;
        }
        else {
            *list = insert(*list, node);
        }
    }

    if(*list) {
        while((*list)->num == 0) {
            (*list)->num = rand() % 10;
        }
    }
}

// 执行两个链表的加法,结果放在sum链表中
void list_add(struct Node *list1, struct Node *list2, struct Node **sum)
{
    int flag;

    struct Node *sump = NULL;
    struct Node *temp = NULL;

    while(list1) {

        temp = (struct Node *)malloc(sizeof(struct Node));

        temp->num = list1->num + list2->num;
        temp->next = NULL;

        if(sump == NULL) {
            sump = temp;
        }
        else {
            sump = insert(sump, temp);
        }

        list1 = list1->next;
        list2 = list2->next;
    }

    *sum = NULL;
    flag = 0;

    while(sump) {
        sump->num = sump->num + flag;
        flag = (sump->num >= 10) ? 1 : 0;
        sump->num = flag ? (sump->num - 10) : (sump->num);
        temp = sump;
        sump = sump->next;
        temp->next = NULL;

        if(*sum == NULL) {
            *sum = temp;
        }
        else {
            *sum = insert(*sum, temp);
        }
    }

    if(flag) {
        temp = (struct Node *)malloc(sizeof(struct Node));
        temp->num = flag;
        temp->next = NULL;
        *sum = insert(*sum, temp);
    }
}

// 查看结果
void list_print(struct Node *list)
{
    while(list) {
        printf("%d", list->num);
        list = list->next;
    }
}

// 释放空间
void list_free(struct Node *list)
{
    struct Node *temp;
    while(list) {
        temp = list;
        temp->next = NULL;
        list = list->next;
        free(temp);
    }
}

只找到了使用两次遍历的方法,使用一次遍历的方法见:link

Author: wangsd

Date: 2013.06.30

HTML generated by org-mode 6.35i in emacs 24

posted @ 2013-06-30 22:43  Let it be!  阅读(2041)  评论(0编辑  收藏  举报