题目:给定两个链表,分别表示两个非负整数。它们的数字逆序存储在链表中,并且每个节点只存储一个数字,计 算两个数的和,并且返回和的链表头指针。
如: 输入:3->6->9,2->5->7,输出:5->1->7->1
思路:1、逆序相加,相当于从两个链表头指针向后依次相加
2、注意两个链表长度可能不同
3、注意可能存在的进位问题
参考答案如下:(其中的细节函数,如Destroy、Print没有实现)
我的实现代码:
// LinkAdd.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef struct Node
{
//public:
int data;
Node* nextPtr;
Node(int value):data(value),nextPtr(NULL){}
};
Node* LinkAdd(Node* HeadNode1,Node* HeadNode2);
int* GetIntValue(int size);
Node* CreateLink(int dataArray[],int n);
void OutputLink(Node* HeadNode);
int _tmain(int argc, _TCHAR* argv[])
{
int len1 = 8;
int len2 = 10;
int* dataArray1 = GetIntValue(len1);/*生成第一个链表对应值的整形数组*/
int* dataArray2 = GetIntValue(len2);
Node* HeadNode1 = CreateLink(dataArray1,len1);/*生成一个链表*/
Node* HeadNode2 = CreateLink(dataArray2,len2);
Node* HeadNode = LinkAdd(HeadNode1,HeadNode2);/*链表相加*/
OutputLink(HeadNode1);//输出链表
OutputLink(HeadNode2);
OutputLink(HeadNode);
/*没有做销毁工作 */
return 0;
}
//链表相加函数实现
Node* LinkAdd(Node* HeadNode1,Node* HeadNode2)
{
Node* HeadNode = new Node(0);
Node* RearNode = HeadNode;
Node* p = new Node(0);
if(HeadNode1 != NULL && HeadNode2 != NULL)
{
int data1 = 0;
int data2 = 0;
int data = 0;
HeadNode->nextPtr = p;
Node* p1 = HeadNode1->nextPtr;
Node* p2 = HeadNode2->nextPtr;
int addition = 0;//进位
while(p1 != NULL || p2 != NULL|| addition !=0)
{
if(p1 != NULL)
{
data1 = p1->data;
p1 = p1->nextPtr;
}
else
{
data1= 0;
}
if(p2 != NULL)
{
data2 = p2->data;
p2 = p2->nextPtr;
}
else
{
data2 = 0;
}
data = data1+data2+addition;
if(data >= 10)
{
data = data-10;
addition = 1;
}
else
{
addition = 0;
}
p = new Node(data);
RearNode->nextPtr = p;
RearNode = RearNode->nextPtr;
}
}
return HeadNode;
}
//链表值将输入存入数组中
int* GetIntValue(int size)
{
int *dataArray = new int[size];
int i;
for(i = 0; i< size; i++)
{
dataArray[i] = (rand()%10);//随机生成数并对其去余数
}
return dataArray;
/* 之后改为根据用户手动输入生成链表,需要判断输入正确性,保证输入为一位正整数*/
}
//根据整形数组创建链表,头结点的指针指向真正链表,头结点的数据域没有值
Node* CreateLink(int dataArray[],int n)
{
Node* HeadNode = new Node(0);
Node* RearNode = HeadNode;
//Node* p = new Node(0);
if(dataArray != NULL && n !=0)
{
int i;
for(i=0; i< n;i++)
{
RearNode->nextPtr = new Node(dataArray[i]);
RearNode = RearNode->nextPtr;
}
}
return HeadNode;//如何考虑空间回收的问题
}
//输出链表
void OutputLink(Node* HeadNode)
{
if(HeadNode == NULL)
{
cout<<"链表为NULL";
}
else
{
//cout<<HeadNode->data;
Node* curNode = HeadNode->nextPtr;
bool firstNode = true;
while(curNode != NULL)
{
if(firstNode)//这样不好,需要每次判断
{
cout << curNode->data;
firstNode = false;
}
else
{
cout<<"->"<<curNode->data;
curNode = curNode->nextPtr;
}
}
cout<<"\n";
}
}
运行结果:
我的总结:
1、关于生成一个新节点
一般书上给出的方法都是:Node *s=(struct Node*)malloc(sizeof(struct Node)); s->data = ...; s->next = ...;
本文采用的方式是在结构体中定义了构造函数 Node(int value):data(value),nextPtr(NULL){}
与下面这种写法等价
Node(int value)
{
data=value;
nextPtr=NULL;
}
创建新的节点方法为Node* HeadNode = new Node(0); 提供参数0为节点的data值,nextPtr指向MULL。
2、本文涉及到插入节点,参考代码使用的是头插法,我使用的是尾插法。
可以参照本文学习 http://blog.csdn.net/behanga/article/details/6701495
3、因为我的实现代码中,先接收整形数据,将其生成数组,然后再将其生成链表,涉及到整形数组的传递问题,调试过程中花了一些时间,主要是对指针和数组在C++中作为 参数和返回值还不太熟练。在C++中,数组不是一种类型,因此不能被直接返回,可以返回指向数组的指针。具体参照 http://blog.sina.com.cn/s/blog_6f26189101012111.html问题得到解决。
4、我认为在实现一个功能时,可以先将问题细化成几部分,将要实现的部分先用伪代码按流程列在Main函数中,然后在逐一实现,这样实现起来比较快速,有条理,且易读,暂且不说实现方法的好坏,通过我的主函数,可以一目了然地看出整个功能的实现流程。
参考答案在主函数中边生成数据边插入链表,而我是先接收所有数据,将它们存储在数组中,后再将数组整体的生成链表。这样将两部分功能分开更清晰,但我也为此付出了消耗内存的代价。两种方法各有利弊,需要权衡。