常见面试编程题
链表中的每个结点除了含有正常的data和next指针成员外,还有一个指向链表随机结点的指针rand,要求完整的复制该链表。
思路:
参考剑指offer
遍历三遍链表:
第一遍:在原链表中的每个结点后插入一个与原结点值相同的新结点,新结点的rand指针设为NULL。
第二遍:将每个新结点的rand指针指向它的原结点(前驱结点)的rand指向的随机结点的下一个结点(新结点)。
第三遍:将链表按奇偶拆分,恢复原链表,得到新链表。
C++代码如下:
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node *rand;
Node(int val) : data(val), next(NULL), rand(NULL) {
;
}
Node & addTail(int val) {
if (this->next) {
return *this;
}
else {
Node *p = new Node(val);
this->next = p;
return *p;
}
}
void addRand(Node & node) {
this->rand = &node;
}
Node & getNext(void) {
if (this->next)
return *(this->next);
else
return *this;
}
// 打印含随机结点的链表,每个结点和它的随机结点占一列
static void printRandList(Node & head){
Node *p = &head;
while (p) {
cout << p->data << " ";
if (p->rand) {
cout << p->rand->data;
}
cout << endl;
p = p->next;
}
}
static Node & copy(Node & head) {
// 第一遍
Node *p = &head;
while (p) {
Node *q = p->next;
Node *tmp = new Node(p->data);
p->next = tmp;
tmp->next = q;
p = q;
}
// 第二遍
p = &head;
while (p) {
Node *q = p->next;
if (p->rand) {
q->rand = p->rand->next;
}
p = q->next;
}
// 第三遍
p = &head;
Node *newHead = p->next;
while (p) {
Node *q = p->next;
p->next = q->next;
p = q->next;
if (p)
q->next = p->next;
else
q->next = NULL;
}
return *newHead;
}
};
int main(int argc, char **argv)
{
// 创建含有随机结点的链表
Node head(1);
head.addTail(2).addTail(3).addTail(4).addTail(5);
head.addRand(head.getNext().getNext());
Node &second = head.getNext();
second.addRand(second.getNext().getNext());
Node &third = second.getNext();
third.addRand(third.getNext().getNext());
Node::printRandList(head);
cout << endl;
Node::printRandList(Node::copy(head));
system("pause");
return 0;
}