链表加法的两种实现

第一种是高位在链表尾部a = 7->1->2b = 4->3result = 1->5->2

没啥说的,注意进位,注意链表长度不一定一样
#include<stdio.h>
#include<stdlib.h>

/* Linked list node */
struct node
{
    int data;
    struct node* next;
};

/* Function to create a new node with given data */
struct node *newNode(int data)
{
    struct node *new_node = (struct node *) malloc(sizeof(struct node));
    new_node->data = data;
    new_node->next = NULL;
    return new_node;
}

/* Function to insert a node at the beginning of the Doubly Linked List */
void push(struct node** head_ref, int new_data)
{
    /* allocate node */
    struct node* new_node = newNode(new_data);

    /* link the old list off the new node */
    new_node->next = (*head_ref);

    /* move the head to point to the new node */
    (*head_ref)    = new_node;
}

/* Adds contents of two linked lists and return the head node of resultant list */
struct node* addTwoLists (struct node* first, struct node* second)
{
    struct node* res = NULL; // res is head node of the resultant list
    struct node *temp, *prev = NULL;
    int carry = 0, sum;

    while (first != NULL || second != NULL) //while both lists exist
    {
        // Calculate value of next digit in resultant list.
        // The next digit is sum of following things
        // (i)  Carry
        // (ii) Next digit of first list (if there is a next digit)
        // (ii) Next digit of second list (if there is a next digit)
        sum = carry + (first? first->data: 0) + (second? second->data: 0);

        // update carry for next calulation
        carry = (sum >= 10)? 1 : 0;

        // update sum if it is greater than 10
        sum = sum % 10;

        // Create a new node with sum as data
        temp = newNode(sum);

        // if this is the first node then set it as head of the resultant list
        if(res == NULL)
            res = temp;
        else // If this is not the first node then connect it to the rest.
            prev->next = temp;

        // Set prev for next insertion
        prev  = temp;

        // Move first and second pointers to next nodes
        if (first) first = first->next;
        if (second) second = second->next;
    }

    if (carry > 0)
      temp->next = newNode(carry);

    // return head of the resultant list
    return res;
}

// A utility function to print a linked list
void printList(struct node *node)
{
    while(node != NULL)
    {
        printf("%d ", node->data);
        node = node->next;
    }
    printf("\n");
}

/* Drier program to test above function */
int main(void)
{
    struct node* res = NULL;
    struct node* first = NULL;
    struct node* second = NULL;

    // create first list 7->5->9->4->6
    push(&first, 6);
    push(&first, 4);
    push(&first, 9);
    push(&first, 5);
    push(&first, 7);
    printf("First List is ");
    printList(first);

    // create second list 8->4
    push(&second, 4);
    push(&second, 8);
    printf("Second List is ");
    printList(second);

    // Add the two lists and see result
    res = addTwoLists(first, second);
    printf("Resultant list is ");
    printList(res);

   return 0;
}
第二种是高位在链表头部
a = 2 -> 1 -> 7
b = 3 -> 4
result = 2 -> 5 -> 1

这个为了处理进位,需要用递归的思想
// A recursive program to add two linked lists

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

// A linked List Node
struct node
{
    int data;
    struct node* next;
};

typedef struct node node;

/* A utility function to insert a node at the beginning of linked list */
void push(struct node** head_ref, int new_data)
{
    /* allocate node */
    struct node* new_node = (struct node*) malloc(sizeof(struct node));

    /* put in the data  */
    new_node->data  = new_data;

    /* link the old list off the new node */
    new_node->next = (*head_ref);

    /* move the head to point to the new node */
    (*head_ref)    = new_node;
}

/* A utility function to print linked list */
void printList(struct node *node)
{
    while (node != NULL)
    {
        printf("%d  ", node->data);
        node = node->next;
    }
    printf("\n");
}

// A utility function to swap two pointers
void swapPointer( node** a, node** b )
{
    node* t = *a;
    *a = *b;
    *b = t;
}

/* A utility function to get size of linked list */
int getSize(struct node *node)
{
    int size = 0;
    while (node != NULL)
    {
        node = node->next;
        size++;
    }
    return size;
}

// Adds two linked lists of same size represented by head1 and head2 and returns
// head of the resultant linked list. Carry is propagated while returning from
// the recursion
node* addSameSize(node* head1, node* head2, int* carry)
{
    // Since the function assumes linked lists are of same size,
    // check any of the two head pointers
    if (head1 == NULL)
        return NULL;

    int sum;

    // Allocate memory for sum node of current two nodes
    node* result = (node *)malloc(sizeof(node));

    // Recursively add remaining nodes and get the carry
    result->next = addSameSize(head1->next, head2->next, carry);

    // add digits of current nodes and propagated carry
    sum = head1->data + head2->data + *carry;
    *carry = sum / 10;
    sum = sum % 10;

    // Assigne the sum to current node of resultant list
    result->data = sum;

    return result;
}

// This function is called after the smaller list is added to the bigger
// lists‘s sublist of same size.  Once the right sublist is added, the carry
// must be added toe left side of larger list to get the final result.
void addCarryToRemaining(node* head1, node* cur, int* carry, node** result)
{
    int sum;

    // If diff. number of nodes are not traversed, add carry
    if (head1 != cur)
    {
        addCarryToRemaining(head1->next, cur, carry, result);

        sum = head1->data + *carry;
        *carry = sum/10;
        sum %= 10;

        // add this node to the front of the result
        push(result, sum);
    }
}

// The main function that adds two linked lists represented by head1 and head2.
// The sum of two lists is stored in a list referred by result
void addList(node* head1, node* head2, node** result)
{
    node *cur;

    // first list is empty
    if (head1 == NULL)
    {
        *result = head2;
        return;
    }

    // second list is empty
    else if (head2 == NULL)
    {
        *result = head1;
        return;
    }

    int size1 = getSize(head1);
    int size2 = getSize(head2) ;

    int carry = 0;

    // Add same size lists
    if (size1 == size2)
        *result = addSameSize(head1, head2, &carry);

    else
    {
        int diff = abs(size1 - size2);

        // First list should always be larger than second list.
        // If not, swap pointers
        if (size1 < size2)
            swapPointer(&head1, &head2);

        // move diff. number of nodes in first list
        for (cur = head1; diff--; cur = cur->next);

        // get addition of same size lists
        *result = addSameSize(cur, head2, &carry);

        // get addition of remaining first list and carry
        addCarryToRemaining(head1, cur, &carry, result);
    }

    // if some carry is still there, add a new node to the fron of
    // the result list. e.g. 999 and 87
    if (carry)
        push(result, carry);
}

// Driver program to test above functions
int main()
{
    node *head1 = NULL, *head2 = NULL, *result = NULL;

    int arr1[] = {9, 9, 9};
    int arr2[] = {1, 8};

    int size1 = sizeof(arr1) / sizeof(arr1[0]);
    int size2 = sizeof(arr2) / sizeof(arr2[0]);

    // Create first list as 9->9->9
    int i;
    for (i = size1-1; i >= 0; --i)
        push(&head1, arr1[i]);

    // Create second list as 1->8
    for (i = size2-1; i >= 0; --i)
        push(&head2, arr2[i]);

    addList(head1, head2, &result);

    printList(result);
    getchar();
    return 0;
}
 
时间: 2024-10-12 00:53:19

链表加法的两种实现的相关文章

反转一个链表的两种方法:递归和循环

下面是反转一个链表的两种方法: 一.循环算法 //反转一个链表,循环算法 LinkList Reverse(LinkList& head) { // if(!head) // return head; //此时不用判断head是否为空,如是空的话返回的也是空 LinkList cur = head; LinkList hou; LinkList beh = 0; while (cur) { hou = cur->next; cur->next = beh; beh = cur; cur

剑指offer_面试题17_合并两个排序的链表(两种思维)

题目:输入两个递增排序的链表,合并这两个链表,并使新链表中的结点仍然是按照递增排序的. 第一种思维:合并两个排序的链表,类似于合并两个排序数组,所不同的仅是一个用链表保存数据,一个用数组保存数据. 算法如下:(下面的算法前提是:头结点 不是 链表的第一个数据节点.) /**方法一:合并两个排序链表,使用了新创建的链表来保存,没有改动两个原始链表*/ ListNode *merge_tow_list(ListNode *pHead1,ListNode *pHead2) { if(NULL == p

两种删除单链表结点的实现,一种O(n),一种O(1)

常规的删除单链表结点的做法是挨个查找到该结点的前一个结点,然后去掉要删除的这个结点,回收内存.这个需要O(n)的时间. 有一种比较快速的删除掉链表指定一个节点的方法,就是把下一个结点的内容复制到当前这个结点,然后把下一次结点删除掉,这个需要考虑当要删除的结点是最后一个结点的情况. 如果刚好是最后一个结点,则需要O(n)的时间,如果不是最后一个结点,可以在O(1)时间内完成删除操作. 1 // 2 // main.c 3 // SingleListDeleteNode 4 // 5 // Crea

以指针和引用两种参数实现删除单链表L中所有值为X的结点的函数

下面是单链表的数据结构 typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*Linklist; 1.以指针参数实现 void delete_x_1(LNode *head,ElemType x){//head为单链表头结点,删除结点的值为x LNode *l = head; LNode *p = head->next; while(p != null){ if(p->data == x){ l->next =

将单链表排序的两种方法

对单链表排序,通常有两种方法.(PS:考察一个程序员的C语言编程功底,通常看他是否能娴熟的操作链表就知道了.) 方法1:将每一个结点保存到额外的数组中,对数组进行排序,然后根据有序的数组重新构建链表. 方法2:直接对链表进行插入排序,但是实现起来比较复杂一些. 显然,方法1最为简单,因为将链式存储L先转化为顺序存储a[],对顺序存储a[]排序,就避免了较为复杂的链接指针操作.一旦对顺序存储a[]排好序后,根据a[]重新构建一个链表是易如反掌的事情. 1. 单链表的定义如下 typedef str

将单链表翻转的两种方法

将一个单链表翻转的描述很简单,例如: 输入: NODE1->NODE2->NODE3->NODE4->NODE5->NULL 输出: NODE5->NODE4->NODE3->NODE2->NODE1->NULL 那么,定义单链表如下: (为简单起见,将data字段定义为int, 当然实际应用中data很可能是一个复杂的结构体) typedef struct list_s { int data; struct list_s *next; } li

约瑟夫环问题的两种实现[链表+数组]

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 以下是使用循环链表和数组的两种实现: 1 #include<iostream> 2 using namespace std; 3 4 struct Node 5 { 6 int data; 7 Node *next; 8 }; 9 void CreateLink

【剑指offer】递归循环两种方式反转链表

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25737023 本文分别用非递归和递归两种方式实现了链表的反转,在九度OJ上AC. 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000):代表将要输入的链表的个数.输入的第二行包含n个整数t(0<=t<=1000000)

用两种递归思路与循环实现单链表的反转

typedef struct ListNode{ int data; struct ListNode *next; }ListNode; //递归一 ListNode *ReverseList (ListNode *pHead, ListNode *nHead = NULL) { //每次取下第一个节点头插法创建新链表 //nHead为反转后链表的头节点 if(pHead == NULL) return NULL; ListNode *pNext = pHead -> next; pHead -