单链表的经典面试题

在之前的文章中,我们已经介绍过了单链表的基本功能的代码实现,下面我们就基于基本的功能,来实现一些关于单链表的经典面试题的代码编写。

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();
}

至此,单链表的经典面试题就全部完成啦。希望能给看到这篇博客的朋友们一点点帮助。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值