用于添加由链表表示的两个数字的 C++ 程序 - 集 2
给定由两个链表表示的两个数字,编写一个返回和列表的函数。和表是两个输入数相加的链表表示。不允许修改列表。此外,不允许使用显式的额外空间(提示:使用递归)。
示例:
Input:
First List: 5->6->3
Second List: 8->4->2
Output:
Resultant list: 1->4->0->5
我们在这里讨论了一个解决方案,它适用于链表,其中最低有效位是列表的第一个节点,最高有效位是最后一个节点。在这个问题中,最高有效节点是第一个节点,最低有效数字是最后一个节点,我们不允许修改列表。这里使用递归来计算从右到左的总和。
以下是步骤。
- 计算给定两个链表的大小。
- 如果大小相同,则使用递归计算总和。将递归调用堆栈中的所有节点保持到最右边的节点,计算最右边的节点的总和并向前进位到左侧。
- 如果大小不同,请按照以下步骤操作:
- 计算两个链表的大小差。让差异有所不同。
- 在更大的链表中将差异节点向前移动。现在使用步骤 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了解更多详情!