📌  相关文章
📜  用于添加由链表表示的两个数字的 C++ 程序 - 集 2

📅  最后修改于: 2022-05-13 01:54:45.929000             🧑  作者: Mango

用于添加由链表表示的两个数字的 C++ 程序 - 集 2

给定由两个链表表示的两个数字,编写一个返回和列表的函数。和表是两个输入数相加的链表表示。不允许修改列表。此外,不允许使用显式的额外空间(提示:使用递归)。

示例

Input:
First List: 5->6->3  
Second List: 8->4->2 

Output:
Resultant list: 1->4->0->5

我们在这里讨论了一个解决方案,它适用于链表,其中最低有效位是列表的第一个节点,最高有效位是最后一个节点。在这个问题中,最高有效节点是第一个节点,最低有效数字是最后一个节点,我们不允许修改列表。这里使用递归来计算从右到左的总和。

以下是步骤。

  1. 计算给定两个链表的大小。
  2. 如果大小相同,则使用递归计算总和。将递归调用堆栈中的所有节点保持到最右边的节点,计算最右边的节点的总和并向前进位到左侧。
  3. 如果大小不同,请按照以下步骤操作:
    • 计算两个链表的大小差。让差异有所不同
    • 在更大的链表中将差异节点向前移动。现在使用步骤 2 计算较大列表的较小列表和右子列表(相同大小)的总和。此外,存储此总和的进位。
    • 计算进位的总和(在上一步中计算)与较大列表的剩余左子列表。该总和的节点被添加到上一步获得的总和列表的开头。

以下是上述方法的试运行:

下图是上述方法的实现。

C++
// A C++ recursive program to add two
// linked lists
#include 
using namespace std;
 
// A linked List Node
class Node
{
    public:
    int data;
    Node* next;
};
 
typedef Node node;
 
/* A utility function to insert
   a node at the beginning of
   linked list */
void push(Node** head_ref,
          int new_data)
{
    // Allocate node
    Node* new_node =
          new Node[(sizeof(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(Node* node)
{
    while (node != NULL)
    {
        cout << node->data << " ";
        node = node->next;
    }
    cout << endl;
}
 
// 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(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 = new Node[(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 front of the result
    // list. e.g. 999 and 87
    if (carry)
        push(result, carry);
}
 
// Driver code
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);
 
    return 0;
}
 
// This code is contributed by rathbhupendra


C++
// C++ Iterative program to add two
// linked lists 
#include 
using namespace std;
   
// A linked List Node 
class Node 
{ 
    public:
    int data; 
    Node* next; 
};
 
// To push a new node to
// linked list
void push(Node** head_ref,
          int new_data) 
{ 
    // Allocate node
    Node* new_node =
          new Node[(sizeof(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; 
}
 
// To add two new numbers
Node* addTwoNumList(Node* l1,
                    Node* l2)
{
    stack s1,s2;
    while(l1 != NULL)
    {
        s1.push(l1->data);
        l1 = l1->next;
    }
    while(l2 != NULL)
    {
        s2.push(l2->data);
        l2 = l2->next;
    }
    int carry = 0;
    Node* result = NULL;
    while(s1.empty() == false ||
          s2.empty() == false)
    {
        int a = 0,b = 0;
        if(s1.empty() == false)
        {
            a = s1.top();
            s1.pop();
        }
        if(s2.empty() == false)
        {
            b = s2.top();
            s2.pop();
        }
        int total = a + b + carry;
        Node* temp = new Node();
        temp->data = total % 10;
        carry = total / 10;
        if(result == NULL)
        {
            result = temp;
        }
        else
        {
            temp->next = result;
            result = temp;
        }
    }
    if(carry != 0)
    {
        Node* temp = new Node();
        temp->data = carry;
        temp->next = result;
        result = temp;
    }
    return result;
}
 
// To print a linked list
void printList(Node *node) 
{ 
    while (node != NULL) 
    { 
        cout << node->data << " "; 
        node = node->next; 
    } 
    cout << endl; 
}
 
// Driver Code
int main() 
{ 
    Node *head1 = NULL,
         *head2 = NULL; 
   
    int arr1[] = {5, 6, 7}; 
    int arr2[] = {1, 8}; 
   
    int size1 = (sizeof(arr1) /
                 sizeof(arr1[0])); 
    int size2 = (sizeof(arr2) /
                 sizeof(arr2[0])); 
   
    // Create first list as 5->6->7 
    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]); 
     
    Node* result =
          addTwoNumList(head1, head2);
    printList(result); 
   
    return 0; 
}


输出:

1 0 1 7

时间复杂度:
O(m+n) 其中 m 和 n 是给定两个链表的大小。

迭代方法:
此实现没有任何递归调用开销,这意味着它是一种迭代解决方案。
因为我们需要从两个链表的最后一个开始添加数字。所以,这里我们将使用栈数据结构来实现这一点。

  • 我们将首先从给定的两个链表中创建两个堆栈。
  • 然后,我们将运行一个循环,直到两个堆栈都为空。
  • 在每次迭代中,我们都会跟踪进位。
  • 最后,如果进位>0,这意味着我们需要在结果列表的开头有额外的节点来容纳这个进位。

C++

// C++ Iterative program to add two
// linked lists 
#include 
using namespace std;
   
// A linked List Node 
class Node 
{ 
    public:
    int data; 
    Node* next; 
};
 
// To push a new node to
// linked list
void push(Node** head_ref,
          int new_data) 
{ 
    // Allocate node
    Node* new_node =
          new Node[(sizeof(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; 
}
 
// To add two new numbers
Node* addTwoNumList(Node* l1,
                    Node* l2)
{
    stack s1,s2;
    while(l1 != NULL)
    {
        s1.push(l1->data);
        l1 = l1->next;
    }
    while(l2 != NULL)
    {
        s2.push(l2->data);
        l2 = l2->next;
    }
    int carry = 0;
    Node* result = NULL;
    while(s1.empty() == false ||
          s2.empty() == false)
    {
        int a = 0,b = 0;
        if(s1.empty() == false)
        {
            a = s1.top();
            s1.pop();
        }
        if(s2.empty() == false)
        {
            b = s2.top();
            s2.pop();
        }
        int total = a + b + carry;
        Node* temp = new Node();
        temp->data = total % 10;
        carry = total / 10;
        if(result == NULL)
        {
            result = temp;
        }
        else
        {
            temp->next = result;
            result = temp;
        }
    }
    if(carry != 0)
    {
        Node* temp = new Node();
        temp->data = carry;
        temp->next = result;
        result = temp;
    }
    return result;
}
 
// To print a linked list
void printList(Node *node) 
{ 
    while (node != NULL) 
    { 
        cout << node->data << " "; 
        node = node->next; 
    } 
    cout << endl; 
}
 
// Driver Code
int main() 
{ 
    Node *head1 = NULL,
         *head2 = NULL; 
   
    int arr1[] = {5, 6, 7}; 
    int arr2[] = {1, 8}; 
   
    int size1 = (sizeof(arr1) /
                 sizeof(arr1[0])); 
    int size2 = (sizeof(arr2) /
                 sizeof(arr2[0])); 
   
    // Create first list as 5->6->7 
    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]); 
     
    Node* result =
          addTwoNumList(head1, head2);
    printList(result); 
   
    return 0; 
}


输出:

5 8 5

相关文章:用链表表示的两个数相加 |设置 1
请参考完整的文章添加链表表示的两个数字 |设置2了解更多详情!