在之前的文章中,我们已经介绍过了单链表的基本功能的代码实现,下面我们就基于基本的功能,来实现一些关于单链表的经典面试题的代码编写。
linklist.h
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
typedef char LinkNodeType;
typedef struct LinkNode{
struct LinkNode* next;
LinkNodeType data;
}LinkNode;
void LinklistInit(LinkNode** node);
void LinklistDestroy(LinkNode** phead);
LinkNode* LinklistPushBack(LinkNode** phead,LinkNodeType value);
void LinklistPopBack(LinkNode** phead);
LinkNode* CreateNode(LinkNodeType value);
void DestroyNode(LinkNode* node);
void LinkNodePrint(LinkNode* head,const char* msg);
void LinklistPushFront(LinkNode** head,LinkNodeType value);
void LinklistPopFront(LinkNode** head);
LinkNode* LinklistFind(LinkNode* head,LinkNodeType to_find);
void LinklistInsertBefore(LinkNode** head,LinkNode* pos,LinkNodeType value);
void LinklistInsertAfter1(LinkNode** head,LinkNode* pos,LinkNodeType value);
void LinklistErase(LinkNode** head,LinkNode* pos);
void LinklistRemove(LinkNode** head,LinkNodeType to_delete);
void LinklistRemove2(LinkNode** head,LinkNodeType to_delete);
void LinklistRemoveAll(LinkNode** head,LinkNodeType value);
int LinklistEmpyty(LinkNode* head);
size_t LinklistSize(LinkNode* head);
LinkNode* JosephCircle(LinkNode* head,int M);
void LinklistReversePrint(LinkNode* head);
void LinklistReverse(LinkNode** head);
void LinklistReverse2(LinkNode** head);
void LinklistInsertAfter2(LinkNode* pos,LinkNodeType value);
void LinklistInsertBefore2(LinkNode** head, LinkNode* pos, LinkNodeType value);
void Swap(LinkNodeType* p1,LinkNodeType* p2);
void LinklistBubbleSort(LinkNode* head);
LinkNode* LinklistMerge(LinkNode* head1,LinkNode* head2);
LinkNode* FindMidNode(LinkNode* head);
LinkNode* FindLastKNode(LinkNode* head,size_t K);
void EraseLastKNode(LinkNode** head, size_t K);
LinkNode* HasCycle(LinkNode* head);
size_t GetCycleLen(LinkNode* head);
LinkNode* GetCycleEntry(LinkNode* head);
LinkNode* HasCross(LinkNode* head1, LinkNode* head2);
int HasCrossWithCycle(LinkNode* head1, LinkNode* head2);
LinkNode* UnionSet(LinkNode* head1,LinkNode* head2);
typedef struct ComplexNode{
LinkNodeType data;
struct ComplexNode* next;
struct ComplexNode* random;
}ComplexNode;
void ComplexNodePrint(ComplexNode* head,const char* msg);
ComplexNode* CreateComplexNode(LinkNodeType value);
size_t Diff(ComplexNode* src, ComplexNode* dest);
ComplexNode* Step(ComplexNode* pos, size_t offset);
ComplexNode* CopyComplex1(ComplexNode* head);
ComplexNode* CopyComplex2(ComplexNode* head);
linklist.c
#include"linklist.h"
单链表的逆序打印
通常我们会想到两种方式来解决这个问题:
1.先将单链表逆置,再按顺序打印;
2.使用递归的方法来打印单链表。
这里我们提倡第二种方法来解决这个问题,一是因为代码量少,可读性强,二是因为第一种方法虽然可以实现链表的逆序打印,但它破坏了链表原本的结构顺序。所以下面我们就来基于第二种方法的思想解决这个问题。
void LinklistReversePrint(LinkNode* head){
if(head == NULL){
return;
}
LinklistReversePrint(head->next);
printf("[%c] ",head->data);
printf("\n");
}
逆置单链表
这里我们可以采用两种方法来解决这个问题:
1.从链表的第二个节点开始,删除一个节点就进行一次头插。
void LinklistReverse(LinkNode** head){
if(head == NULL){
return;
}
if(*head == NULL){
return;
}
if((*head)->next == NULL){
return;
}
LinkNode* cur = *head;
LinkNode* to_delete = NULL;
while(cur->next != NULL){
to_delete = cur->next;
cur->next = to_delete->next;
LinklistPushFront(head,to_delete->data);
DestroyNode(to_delete);
}
}
2.改变节点的指向
void LinkListReverse2(LinkNode** head){
if (head == NULL){
return; //非法输入
}
if (*head == NULL){
return; //空链表
}
if ((*head)->next == NULL){
return; //只有一个元素
}
LinkNode* pre = *head;
LinkNode* cur = (*head)->next;
pre->next = NULL;
while (cur != NULL){
LinkNode* next = cur->next;
cur->next = pre; //重置了当前结点的next
pre = cur;
cur = next;
}
*head = pre;
return;
}
不允许遍历链表,在pos之后插入
void LinklistInsertAfter2(LinkNode* pos,LinkNodeType value){
if(pos == NULL){
return;
}
LinkNode* new_node = CreateNode(value);
new_node->next = pos->next;
pos->next = new_node;
}
不允许遍历链表,在pos之前插入
这个问题我们可以基于在pos之后插入的问题解决,只要在pos之后插入,然后交换pos和pos->next的值,就相当于在不遍历链表的前提下完成了在pos之前插入。
void LinklistInsertBefore2(LinkNode** head, LinkNode* pos, LinkNodeType value){ //不允许遍历
if(head == NULL){
return;
}
if(*head == NULL){
return;
}
LinklistInsertAfter2(pos,value);
LinkNodeType tmp = pos->data;
pos->data = pos->next->data;
pos->next->data = tmp;
}
单链表的冒泡排序
冒泡排序的基本思想是将相邻两元素间两两比较,一趟排序过后,最大的元素就到达了最后。单链表的冒泡排序也是如此,万变不离其宗,我们直接上代码:
void Swap(LinkNodeType* p1,LinkNodeType* p2){
LinkNodeType tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void LinklistBubbleSort(LinkNode* head){
if(head == NULL){
return;
}
LinkNode* cur = head;
LinkNode* count = head;
LinkNode* tail = NULL;
for(cur = head;cur->next != NULL;cur = cur->next){
for(count = head;count->next != tail;count = count->next){
if(count->data > count->next->data){
Swap(&count->data,&count->next->data);
}
}
tail = count;
}
}
将两个有序链表合并成一个有序链表
LinkNode* LinklistMerge(LinkNode* head1, LinkNode* head2){
if(head1 == NULL){
return head2;
}
if(head2 == NULL){
return head1;
}
LinkNode* new_head = NULL;
LinkNode* new_tail = NULL;
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
if(cur1->data > cur2->data){
new_head = cur2;
cur2 = cur2->next;
}
else{
new_head = cur1;
cur1 = cur1->next;
}
new_tail = new_head;
while(cur1 != NULL && cur2 != NULL){
if(cur1->data > cur2->data){
new_tail->next = cur2;
new_tail = cur2;
cur2 = cur2->next;
}
else{
new_tail->next = cur1;
new_tail = cur1;
cur1 = cur1->next;
}
}
if(cur1 != NULL){
new_tail->next = cur1;
}
if(cur2 != NULL){
new_tail->next = cur2;
}
return new_head;
}
查找单链表的中间节点(要求只能遍历一次链表)
LinkNode* FindMidNode(LinkNode* head){
if(head == NULL){
return NULL;
}
LinkNode* fast = head;
LinkNode* slow = head;
while(fast != NULL){
fast = fast->next;
if(fast == NULL){
break;
}
fast = fast->next;
slow = slow->next;
}
printf("the middle node is %c\n",slow->data);
return slow;
}
查找单链表的倒数第k个节点(要求只能遍历一次链表)
这道题的解题思路与上一道题类似。
LinkNode* FindLastKNode(LinkNode* head, size_t K){
if(head == NULL){
return NULL;
}
LinkNode* fast = head;
LinkNode* slow = head;
int i = 0;
for(i = 0;i < K; ++i){
if(fast == NULL){
break;
}
fast = fast->next;
}
while(fast != NULL){
slow = slow->next;
fast = fast->next;
}
printf("the last k node is %c\n",slow->data);
return slow;
}
删除链表的倒数第k个节点
void EraseLastKNode(LinkNode** head, size_t K){
if(head == NULL){
return;
}
if(*head == NULL){
return;
}
size_t len = LinklistSize(*head);
if(K > len){
return;
}
if(K == len){
LinklistPopFront(head);
return;
}
int i = 0;
LinkNode* fast = *head;
for(i = 0;i < len-K-1;++i){
fast = fast->next;
}
LinkNode* to_delete = fast->next;
fast->next = to_delete->next;
DestroyNode(to_delete);
}
判断单链表是否带环
LinkNode* HasCycle(LinkNode* head){
if(head == NULL){
return;
}
LinkNode* fast = head;
LinkNode* slow = head;
while(fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
return slow;
}
}
return NULL;
}
若链表带环,求环长度
size_t GetCycleLen(LinkNode* head){
if(head == NULL){
return 0;
}
LinkNode* meet_node = HasCycle(head);
if(meet_node == NULL){
return 0;
}
size_t len = 1;
LinkNode* cur = meet_node->next;
for(;cur != meet_node;cur = cur->next){
++len;
}
return len;
}
若链表带环,求环的入口
先判断链表是否带环,若带环,定义两个指针,分别指向链表的头结点和相遇点,然后两个指针一起一次走一步,直到相遇,此时指针指向的位置即为入口点。
LinkNode* GetCycleEntry(LinkNode* head){
if(head == NULL){
return;
}
LinkNode* meet_node = HasCycle(head);
if(meet_node == NULL){
return NULL;
}
LinkNode* cur1 = head;
LinkNode* cur2 = meet_node;
while(cur1 != cur2){
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
判断两链表是否相交(假设单链表不带环)
链表不带环时,可分为两种情况:
1.两链表不相交
2.两链表相交,此时为y形
注:不存在X形的相交链表,因为链表只能由一个节点指向另外一个节点,而X形相交节点的指针要指向两个节点,不符合客观事实,因此不存在这种情况。
解题思路:
LinkNode* HasCross(LinkNode* head1, LinkNode* head2){
if(head1 == NULL || head2 == NULL){
return;
}
size_t len1 = LinklistSize(head1);
size_t len2 = LinklistSize(head2);
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
if(len1 > len2){
size_t i = 0;
for(;i < len1-len2;++i){
cur1 = cur1->next;
}
}
else if(len1 < len2){
size_t i = 0;
for(;i < len2-len1;++i){
cur2 = cur2->next;
}
}
while(cur1 != cur2){
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
判断两链表是否相交(假设单链表可能带环)
可能出现的几种情况:
1.两链表均为单链表。此时可以用调用上道题的函数直接进行判断;
2.一个带环一个不带环,此时两个链表必定不相交;
3.两个链表均带环。这里我们又要分两种情况来讨论:
a)不相交
b)交点在环上
c)交点在环外
int HasCrossWithCycle(LinkNode* head1, LinkNode* head2){
if(head1 == NULL || head2 == NULL){
return 0;
}
//1.先判断两个连表是否带环
LinkNode* entry1 = HasCycle(head1);
LinkNode* entry2 = HasCycle(head2);
//2.若两个都不带环,就可以用HasCross函数来判断
if(entry1 == NULL && entry2 == NULL){
return HasCross(head1,head2) != NULL ? 1 : 0;
}
//3.若一个带环一个不带环,则直接返回NULL
else if((entry1==NULL && entry2!=NULL)||(entry1!=NULL && entry2==NULL)){
return 0;
}
//4.若两个链表都带环,则:
else if(entry1 != NULL && entry2 != NULL){
// a)交点在环外
if(entry1 == entry2){
return 1;
}
// b)交点在环内
LinkNode* cur = entry1;
while(cur->next != entry1){
if(cur == entry2){
return 1;
}
cur = cur->next;
}
return 0;
}
else{
return 0;
}
return 0;
}
求两个已排序单链表中的相同数据
LinkNode* UnionSet(LinkNode* head1,LinkNode* head2){
if(head1 == NULL || head2 == NULL){
return NULL;
}
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
LinkNode* new_head = NULL;
LinkNode* new_tail = NULL;
while(cur1 != NULL && cur2 != NULL){
if(cur1->data > cur2->data){
cur2 = cur2->next;
}
else if(cur1->data < cur2->data){
cur1 =cur1->next;
}
else{
LinkNode* new_node = CreateNode(cur1->data);
if(new_head == NULL){
new_head = new_tail = new_node;
}
else{
new_tail->next = new_node;
new_tail = new_tail->next;
}
cur1 = cur1->next;
cur2 = cur2->next;
}
}
return new_head;
}
复杂链表的复制
首先我们先做准备工作,在头文件中新定义一个结构体类型ComplexNode,然后编写两个基本功能的函数来实现打印和创造节点。
void ComplexNodePrint(ComplexNode* head,const char* msg){
printf("[%s]\n",msg);
ComplexNode* cur = head;
for(;cur != NULL;cur = cur->next){
printf("[%c]",cur->data);
}
printf("\n");
}
ComplexNode* CreateComplexNode(LinkNodeType value){
ComplexNode* new_node = (ComplexNode*)malloc(sizeof(ComplexNode));
new_node->data = value;
new_node->next = NULL;
new_node->random = NULL;
return new_node;
}
做完准备工作,我们正式解决问题。这里我们提供两种方法:
1.先将单链表进行简单复制,再依次求每个random指针相对头节点的偏移量,根据偏移量,修改每个新链表节点的random指针
size_t Diff(ComplexNode* src,ComplexNode* dest){
if(src == NULL || dest == NULL){
return (size_t)-1;
}
size_t count = 0;
while(src != NULL){
if(src == dest){
break;
}
++count;
src = src->next;
}
if(src == NULL){
return (size_t)-1;
}
return count;
}
ComplexNode* Step(ComplexNode* pos,size_t offset){
size_t i = 0;
for(;i < offset;++i){
if(pos == NULL){
return NULL;
}
pos = pos->next;
}
return pos;
}
ComplexNode* CopyComplex1(ComplexNode* head){
if(head == NULL){
return NULL;
}
//先将单链表进行简单复制
ComplexNode* new_head = NULL;
ComplexNode* new_tail = NULL;
ComplexNode* cur = head;
for(;cur != NULL;cur = cur->next){
ComplexNode* new_node = CreateComplexNode(cur->data);
if(new_head == NULL){
new_head = new_tail = new_node;
}
else{
new_tail->next = new_node;
new_tail = new_tail->next;
}
}
//再依次求每个random指针相对头节点的偏移量
ComplexNode* new_cur = new_head;
for(cur=head;cur!=NULL && new_cur!=NULL;cur=cur->next,new_cur=new_cur->next){
if(cur->random == NULL){
new_cur->random = NULL;
continue;
}
//根据偏移量,修改每个新链表节点的random指针
size_t offset = Diff(head,cur->random);
new_cur->random = Step(new_head,offset);
}
return new_head;
}
2.第二种方法我们分成三步来完成:
a)遍历旧链表,给每个节点都创造一个新节点,并将新节点插入到旧节点之后;
b)再遍历链表,更新每个新节点的random指针;
c)再遍历链表,将新节点依次拆下来,组成一个新链表。
ComplexNode* CopyComplex2(ComplexNode* head){
//遍历旧链表,给每个节点都创建一个新节点,并将新节点插入到旧节点之后
ComplexNode* cur = head;
for(;cur != NULL;cur = cur->next->next){
ComplexNode* new_node = CreateComplexNode(cur->data);
new_node->next = cur->next;
cur->next = new_node;
}
//再遍历链表,更新每个新节点的random指针
for(cur = head;cur != NULL;cur = cur->next->next){
if(cur->random == NULL){
cur->next->random = NULL;
continue;
}
cur->next->random = cur->random->next;
}
//再遍历链表,将新节点依次拆下来,组成一个新链表
ComplexNode* new_head = NULL;
ComplexNode* new_tail = NULL;
for(cur = head;cur != NULL;cur = cur->next){
ComplexNode* to_delete = cur->next;
cur->next = to_delete->next;
if(new_head == NULL){
new_head = new_tail = to_delete;
}
else{
new_tail->next = to_delete;
new_tail = new_tail->next;
}
}
return new_head;
}
test.c
#include"linklist,c"
void TestReversePrint(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinklistReversePrint(head);
}
void TestReverse(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinklistReverse(&head);
LinkNodePrint(head,"逆置单链表1");
}
void TestReverse2(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinkNodePrint(head,"尾插四个节点");
LinkListReverse2(&head);
LinkNodePrint(head,"逆置单链表2");
}
void TestInsertAfter2(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinkNode* pos = LinklistFind(head,'b');
LinklistInsertAfter2(pos,'x');
LinkNodePrint(head,"在固定位置之后插入一个元素");
}
void TestInsertBefore2(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinkNode* pos = LinklistFind(head,'b');
LinklistInsertBefore2(&head,pos,'x');
LinkNodePrint(head,"在固定位置之前插入一个元素");
}
void TestBubbleSort(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'x');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'h');
LinklistPushBack(&head,'c');
LinklistBubbleSort(head);
LinkNodePrint(head,"单链表冒泡排序");
}
void TestMerge(){
PRINT_HEAD;
LinkNode* head1;
LinklistInit(&head1);
LinklistPushBack(&head1,'a');
LinklistPushBack(&head1,'f');
LinklistPushBack(&head1,'k');
LinklistPushBack(&head1,'x');
LinkNode* head2;
LinklistInit(&head2);
LinklistPushBack(&head2,'c');
LinklistPushBack(&head2,'s');
LinklistPushBack(&head2,'u');
LinklistPushBack(&head2,'z');
LinkNode* result = LinklistMerge(head1,head2);
LinkNodePrint(result,"将两个有序链表, 合并成一个有序链表");
}
void TestFindMidNode(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinklistPushBack(&head,'e');
FindMidNode(head);
}
void TestFindLastKNode(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinklistPushBack(&head,'e');
FindLastKNode(head,2);
}
void TestEraseLastKNode(){
PRINT_HEAD;
LinkNode* head;
LinklistInit(&head);
LinklistPushBack(&head,'a');
LinklistPushBack(&head,'b');
LinklistPushBack(&head,'c');
LinklistPushBack(&head,'d');
LinklistPushBack(&head,'e');
EraseLastKNode(&head,2);
LinkNodePrint(head,"删除倒数第K个节点");
}
void TestHasCycle(){
PRINT_HEAD;
LinkNode* a = CreateNode('a');
LinkNode* b = CreateNode('b');
LinkNode* c = CreateNode('c');
LinkNode* d = CreateNode('d');
LinkNode* e = CreateNode('e');
LinkNode* f = CreateNode('f');
LinkNode* g = CreateNode('g');
a->next = b;
b->next = c;
c->next = d;
d->next = e;
e->next = f;
f->next = g;
g->next = c;
LinkNode* pos = HasCycle(a);
printf("链表有环,相遇点为:%c\n",pos->data);
}
void TestCycleLen(){
PRINT_HEAD;
LinkNode* a = CreateNode('a');
LinkNode* b = CreateNode('b');
LinkNode* c = CreateNode('c');
LinkNode* d = CreateNode('d');
LinkNode* e = CreateNode('e');
LinkNode* f = CreateNode('f');
LinkNode* g = CreateNode('g');
a->next = b;
b->next = c;
c->next = d;
d->next = e;
e->next = f;
f->next = g;
g->next = c;
size_t len = GetCycleLen(a);
printf("链表有环,环长为:%lu\n",len);
}
void TestGetCycleEntry(){
PRINT_HEAD;
LinkNode* a = CreateNode('a');
LinkNode* b = CreateNode('b');
LinkNode* c = CreateNode('c');
LinkNode* d = CreateNode('d');
LinkNode* e = CreateNode('e');
LinkNode* f = CreateNode('f');
LinkNode* g = CreateNode('g');
a->next = b;
b->next = c;
c->next = d;
d->next = e;
e->next = f;
f->next = g;
g->next = c;
LinkNode* entry = GetCycleEntry(a);
printf("链表有环,环的入口点为:%c\n",entry->data);
}
void TestHasCross(){
PRINT_HEAD;
LinkNode* head1;
LinklistInit(&head1);
LinklistPushBack(&head1,'a');
LinkNode* pf = LinklistPushBack(&head1,'f');
LinklistPushBack(&head1,'h');
LinklistPushBack(&head1,'t');
LinkNode* head2;
LinklistInit(&head2);
LinklistPushBack(&head2,'c');
LinklistPushBack(&head2,'e');
LinkNode* pg =LinklistPushBack(&head2,'g');
pg->next = pf;
LinkNode* cross = HasCross(head1,head2);
printf("expect f , actual %c\n",cross->data);
}
void TestHasCrossWithCycle(){
PRINT_HEAD;
LinkNode* head1;
LinklistInit(&head1);
LinkNode* pa = LinklistPushBack(&head1,'a');
LinkNode* pb = LinklistPushBack(&head1,'b');
LinkNode* pc = LinklistPushBack(&head1,'c');
LinkNode* pd = LinklistPushBack(&head1,'d');
pd->next = pc;
LinkNode* head2;
LinklistInit(&head2);
LinklistPushBack(&head2,'e');
LinklistPushBack(&head2,'f');
LinkNode* pg = LinklistPushBack(&head2,'g');
pg->next = pb;
int ret = HasCrossWithCycle(head1,head2);
printf("ret expect 1,actual %d\n",ret);
}
void TestUnionSet(){
PRINT_HEAD;
LinkNode* head1 = NULL;
LinklistInit(&head1);
LinklistPushBack(&head1,'a');
LinklistPushBack(&head1,'b');
LinklistPushBack(&head1,'c');
LinklistPushBack(&head1,'d');
LinkNode* head2 = NULL;
LinklistInit(&head2);
LinklistPushBack(&head2,'b');
LinklistPushBack(&head2,'d');
LinklistPushBack(&head2,'e');
LinklistPushBack(&head2,'f');
LinkNode* new_head = UnionSet(head1,head2);
LinkNodePrint(new_head,"两链表的交集");
}
void TestCopyComplex1(){
PRINT_HEAD;
ComplexNode* a = CreateComplexNode('a');
ComplexNode* b = CreateComplexNode('b');
ComplexNode* c = CreateComplexNode('c');
ComplexNode* d = CreateComplexNode('d');
a->next = b;
b->next = c;
c->next = d;
d->next = NULL;
a->random = c;
b->random = a;
c->random = NULL;
d->random = d;
ComplexNode* new_head1 = CopyComplex1(a);
printf("new_head1:%p\n",new_head1);
}
void TestCopyComplex2(){
PRINT_HEAD;
ComplexNode* a = CreateComplexNode('a');
ComplexNode* b = CreateComplexNode('b');
ComplexNode* c = CreateComplexNode('c');
ComplexNode* d = CreateComplexNode('d');
a->next = b;
b->next = c;
c->next = d;
d->next = NULL;
a->random = c;
b->random = a;
c->random = NULL;
d->random = d;
ComplexNode* new_head2 = CopyComplex2(a);
printf("new_head2:%p\n",new_head2);
}
int main(){
TestReversePrint();
TestReverse();
TestReverse2();
TestInsertAfter2();
TestInsertBefore2();
TestBubbleSort();
TestMerge();
TestFindMidNode();
TestFindLastKNode();
TestEraseLastKNode();
TestHasCycle();
TestCycleLen();
TestGetCycleEntry();
TestHasCross();
TestHasCrossWithCycle();
TestUnionSet();
TestCopyComplex1();
TestCopyComplex2();
}
至此,单链表的经典面试题就全部完成啦。希望能给看到这篇博客的朋友们一点点帮助。