用单链表实现两个大整数相加运算

/**
*   用单链表实现两个大整数相加运算
*   目的:深入掌握单链表应用的算法设计
*   主要功能:
*   1、将用户输入的十进制整数字符串转化为带头结点的单链表,每个结点存放一个整数位
*   2、求两个整数单链表相加的结果单链表
*   3、求结果单链表的中间位,如123的中间位为2,1234的中间位为2
*   @date:2018-01-14
*   @author:xiezhi
*/

#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define MAX_SIZE 50

typedef struct node
{
    int data; // 数据域
    struct node *next; // 指针域
}NodeType;

/*------------------------创建整数单链表--------------------------*/
static void create_list(NodeType *&h, char a[], int n)// 指针的引用
{
    NodeType *p, *r;
    int i = 0;

    // 创建头结点
    h = (NodeType *)malloc(sizeof(NodeType));
    r = h; // r指向新创建的头结点

    while(i < n)
    {
        // 创建新结点p
        p = (NodeType *)malloc(sizeof(NodeType));
        p->data = a[n - i - 1] - '0';
        // 将新结点p插入到r结点之后
        r->next = p;
        // r指向新结点p
        r = p;
        i++;
    }

    r->next = NULL;
}

/*------------------------输出整数单链表--------------------------*/
static void display_list(NodeType *h)
{
    NodeType *p = h->next; // p指向整数单链表的第一个数据结点

    while(p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

/*------------------------释放整数单链表--------------------------*/
static void destroy_list(NodeType *&h)
{
    NodeType *pre = h; // pre指向整数单链表的头结点
    NodeType *p = pre->next; // p指向整数单链表的第一个数据结点

扫描二维码关注公众号,回复: 4935908 查看本文章

    while(p != NULL)
    {
        free(pre);
        // pre,p同步后移一个结点
        pre = p;
        p = p->next;
    }
    free(pre);
}

/*------------------------两整数单链表h1和h2相加得到h--------------------------*/
static void add_list(NodeType *h1, NodeType *h2, NodeType *&h) // 指针的引用
{
    NodeType *p1 = h1->next; // p1指向单链表h1中的第一个数据结点
    NodeType *p2 = h2->next; // p2指向单链表h2中的第一个数据结点
    NodeType *p, *r;
    int carry = 0;

    // 创建头结点
    h = (NodeType *)malloc(sizeof(NodeType));
    // r指向新创建头结点
    r = h;

    while(p1 != NULL && p2 != NULL)
    {
        // 创建新结点p
        p = (NodeType *)malloc(sizeof(NodeType));
        p->data = (p1->data + p2->data + carry) % 10; // 求余
        // 将新结点p插入到r指向的头结点之后
        r->next = p;
        // r后移一个结点
        r = p;
        carry = (p1->data + p2->data + carry) / 10; // 求商
        // p1和p2指向下一个结点
        p1 = p1->next;
        p2 = p2->next;
    }

    if(p1 == NULL)
        p1 = p2;

    while(p1 != NULL)
    {
        p = (NodeType *)malloc(sizeof(NodeType));
        p->data = (p1->data + carry) % 10; // 数据域
        // 将新结点p插入到r指向的头结点之后
        r->next = p;
        // r后移一个结点
        r = p;
        carry = (p1->data + carry) / 10;
        p1 = p1->next;
    }

    // 最后carry不为0时,创建一个结点存放它
    if(carry > 0)
    {
        p = (NodeType *)malloc(sizeof(NodeType));
        p->data = carry;
        // 将新结点p插入到r指向的头结点之后
        r->next = p;
        // r后移一个结点
        r = p;
    }
    r->next = NULL;
}

/*------------------------逆置整数单链表h--------------------------*/
static void reverse_list(NodeType *&h)
{
    NodeType *p = h->next, *q;
    h->next = NULL;

    while(p != NULL)
    {
        q = p->next;
        p->next = h->next;
        h->next = p;
        p = q;
    }
}

/*------------------------求整数单链表h的中间位--------------------------*/
/**
*   算法设计思路:
*   定义快指针quick和慢指针slow,初始时都指向头结点,当快指针没有
*   扫描完整数单链表h时,每次让慢指针slow前进一个结点,快指针quick前进两个
*   结点.当快指针到达链表尾时,慢指针slow指向的结点就是中间结点.
*/
static int mid_list(NodeType *h)
{
    NodeType *slow = h; // 定义慢指针
    NodeType *quick = h; // 定义快指针

    while(quick != NULL && quick->next != NULL)
    {
        slow = slow->next; // 慢指针slow前进一个结点
        quick = quick->next->next; // 快指针quick前进两个结点
    }
    return slow->data;
}

int main(int argc, char *argv[])
{
    NodeType *h1, *h2, *h;
    char s[MAX_SIZE], t[MAX_SIZE];

    printf("操作步骤:\n");
    printf("   (1)输入整数1: ");
    scanf("%s", s);
    printf("   (2)输入整数2: ");
    scanf("%s", t);

    create_list(h1, s, strlen(s));
    create_list(h2, t, strlen(t));

    printf("   (3)整数单链表1: ");
    display_list(h1);
    printf("   (4)整数单链表2: ");
    display_list(h2);

    add_list(h1, h2, h);
    printf("   (5)结果单链表: ");
    display_list(h);

    reverse_list(h);
    printf("   (6)对应的整数: ");
    display_list(h);
    printf("   (7)中间位: %d", mid_list(h));

    destroy_list(h);
    destroy_list(h1);
    destroy_list(h2);

    return 0;
}
运算结果:

操作步骤:
   (1)输入整数1: 99999999
   (2)输入整数2: 666666661
   (3)整数单链表1: 9 9 9 9 9 9 9 9
   (4)整数单链表2: 1 6 6 6 6 6 6 6 6
   (5)结果单链表: 0 6 6 6 6 6 6 6 7
   (6)对应的整数: 7 6 6 6 6 6 6 6 0
   (7)中间位: 6

猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/86480933