C语言实现链表及链表常见面试题

List.h

#ifndef List_h
#define List_h
struct ListNode
{
    int data;
    struct ListNode* pNext;
};

void InitList(struct ListNode** pHead); //初始化
struct ListNode* CreateNode(int data);//创建结点
void PushBack(struct ListNode** pHead, int data);//尾插
void PopBack(struct ListNode** pHead);//尾删
void PushFront(struct ListNode** pHead, int data);//头插
void PopFront(struct ListNode** pHead);//头删
struct ListNode* Find(struct ListNode* pHead, int data);//查找数据data
void Erase(struct ListNode** pHead, struct ListNode* pos);//删除pos位置节点
void Insert(struct ListNode** pHead, struct ListNode* pos, int data);//在pos位置插入节点data
void DestroyList(struct ListNode** pHead);//删除链表
void PrintList(struct ListNode* pHead);//打印链表

void PrintListTailToHead(struct ListNode* pHead);//从尾到头打印单链表
void InsertNotHead(struct ListNode* pos, int data);//在非头节点插入数据data
void DelNotTailNode(struct ListNode* pos);//删除不是尾节点的节点
struct ListNode* FindMidNode(struct ListNode* pHead);//查找中间节点
struct ListNode* JosephCircle(struct ListNode* pHead, int M);//约瑟夫环
void ReverseList(struct ListNode** pHead);//反转单链表
void SortList(struct ListNode* pHead);//排序单链表
struct ListNode* FindLastKNode(struct ListNode* pHead, int K);//查找倒数第K个节点
int GetCyleLen(struct ListNode* pMeetNode);//获得环长度
struct ListNode* HasCycle(struct ListNode* pHead);//判断链表是否有环
struct ListNode* MergeList(struct ListNode* pL1, struct ListNode* pL2);//合并两个单链表
struct ListNode* FindEnterNode(struct ListNode* pHead, struct ListNode* pMeetNode);//
int IsListCrose(struct ListNode* pL1, struct ListNode* pL2);//判断两个链表是否相交
int IsListCroseWithCycle(struct ListNode* pL1, struct ListNode* pL2);//判断两个链表是否环内相交

#endif /* List_h */

List.c

#include "List.h"

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

void InitList(struct ListNode** pHead)//初始化
{
    *pHead = NULL;
}

struct ListNode* CreateNode(int data)//创建结点
{
    struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
    if (node == NULL) {
        return NULL;
    }
    node->data = data;
    node->pNext = NULL;
    return node;
}

void PushBack(struct ListNode** pHead, int data)//尾插
{
    assert(pHead != NULL);
    if (*pHead == NULL) {
        *pHead = CreateNode(data);
        return;
    }
    struct ListNode* node = *pHead;
    while (node->pNext) {
        node = node->pNext;
    }
    node->pNext = CreateNode(data);
}

void PopBack(struct ListNode** pHead)//尾删
{
    assert(pHead != NULL);
    if (*pHead == NULL) {
        return;
    } else if ((*pHead)->pNext == NULL) {
        free(*pHead);
        *pHead = NULL;
    } else {
        struct ListNode* pNode = *pHead;
        struct ListNode* pPreNode = NULL;
        while (pNode->pNext) {
            pPreNode = pNode;
            pNode = pNode->pNext;
        }
        pPreNode->pNext = pNode->pNext;
        free(pNode);
        pNode = NULL;
    }
}

void PushFront(struct ListNode** pHead, int data)//头插
{
    assert(pHead != NULL);
    struct ListNode* node = CreateNode(data);
    if (node != NULL) {
        node->pNext = *pHead;
        *pHead = node;
    }
}

void PopFront(struct ListNode** pHead)//头删
{
    assert(pHead != NULL);
    if (*pHead == NULL) {
        return;
    }
    struct ListNode* node = *pHead;
    *pHead = (*pHead)->pNext;
    free(node);
    node = NULL;
}

struct ListNode* Find(struct ListNode* pHead, int data)//查找数据data
{
    assert(pHead != NULL);
    struct ListNode* node = pHead;
    while (node) {
        if (node->data == data) {
            return node;
        }
        node = node->pNext;
    }
    return NULL;
}

void Erase(struct ListNode** pHead, struct ListNode* pos)//删除pos位置节点
{
    assert(pHead != NULL);
    assert(pos != NULL);
    if (*pHead == pos) {
        *pHead = pos->pNext;
        free(pos);
        pos = NULL;
        return;
    }
    struct ListNode* node = *pHead;
    while (node) {
        if (node->pNext == pos) {
            node->pNext = pos->pNext;
            free(pos);
            pos = NULL;
            return;
        }
        node = node->pNext;
    }
}

void Insert(struct ListNode** pHead, struct ListNode* pos, int data)//在pos位置插入节点data
{
    assert(pHead != NULL);
    assert(pos != NULL);
    struct ListNode* newNode = CreateNode(pos->data);
    if (newNode != NULL) {
        newNode->pNext = pos->pNext;
        pos->pNext = newNode;
        pos->data = data;
    }
}

void DestroyList(struct ListNode** pHead)//删除链表
{
    assert(pHead != NULL);
    struct ListNode* delNode = NULL;
    while (*pHead) {
        delNode = *pHead;
        *pHead = (*pHead)->pNext;
        free(delNode);
        delNode = NULL;
    }
}
void PrintList(struct ListNode* pHead)//打印链表
{
    struct ListNode* node = pHead;
    while (node != NULL) {
        printf("%d->",node->data);
        node = node->pNext;
    }
    printf("NULL\n");
}

void PrintListTailToHead(struct ListNode* pHead)//从尾到头打印单链表
{
    if (pHead != NULL) {
        PrintListTailToHead(pHead->pNext);
        printf("%d ",pHead->data);
    }
}

void InsertNotHead(struct ListNode* pos, int data)//在非头节点插入数据data
{
    assert(pos != NULL);
    struct ListNode* pNewNode = CreateNode(pos->data);
    if (pNewNode != NULL) {
        pNewNode->pNext = pos->pNext;
        pos->pNext = pNewNode;
        pos->data = data;
    }
}

void DelNotTailNode(struct ListNode* pos)//删除不是尾节点的节点
{
    assert(pos != NULL);
    assert(pos->pNext != NULL);
    struct ListNode* pDelNode = pos->pNext;
    pos->data = pos->pNext->data;
    pos->pNext = pos->pNext->pNext;
    free(pDelNode);
    pDelNode = NULL;
}

struct ListNode* FindMidNode(struct ListNode* pHead)//查找中间节点
{
    assert(pHead != NULL);
    struct ListNode* pfast = pHead;
    struct ListNode* pslow = pHead;
    while (pfast != NULL && pfast->pNext != NULL) {
        pfast = pfast->pNext->pNext;
        pslow = pslow->pNext;
    }
    return pslow;
}

/*
 *约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,
 *数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依次规律重复下去,直到圆桌周围的人全部出列
 */
struct ListNode* JosephCircle(struct ListNode* pHead, int M)//约瑟夫环
{
    struct ListNode* pNode = pHead;
    struct ListNode* pDelNode;
    int K = M;
    if (pHead == NULL || M <= 0) {
        return NULL;
    }
    while (pNode->pNext != pNode) {
        K = M;
        while (--K) {
            pNode = pNode->pNext;
        }
        pDelNode = pNode->pNext;
        pNode->data = pDelNode->data;
        pNode->pNext = pDelNode->pNext;
        free(pDelNode);
    }
    return NULL;
}

void ReverseList(struct ListNode** pHead) //反转单链表
{
    struct ListNode* pNewNode = NULL;
    struct ListNode* pPreNode = NULL;
    struct ListNode* pNode = *pHead;
    if (*pHead == NULL || (*pHead)->pNext == NULL)
        return;
    while (pNode) {
        pPreNode = pNode;
        pNode = pNode->pNext;
        
        pPreNode->pNext = pNewNode;
        pNewNode = pPreNode;
    }
    *pHead = pNewNode;
}

void SortList(struct ListNode* pHead) //排序单链表
{
    struct ListNode* pTailNode = NULL;
    struct ListNode* pNode = NULL;
    struct ListNode* pPreNode = NULL;
    if (pHead == NULL)
        return;
    
    while(pHead != pTailNode) {
        pNode = pHead;
        while(pNode->pNext != pTailNode) {
            pPreNode = pNode;
            pNode = pNode->pNext;
            if (pPreNode->data > pNode->data) {
                int data = pPreNode->data;
                pPreNode->data = pNode->data;
                pNode->data = data;
            }
        }
        pTailNode = pNode;
    }
}

struct ListNode* FindLastKNode(struct ListNode* pHead, int K) //查找倒数第K个节点
{
    if (pHead == NULL || K <= 0)
        return NULL;
    
    struct ListNode* pFast = pHead;
    struct ListNode* pSlow = pHead;
    while (K--) {
        if(pFast == NULL)
            return NULL;
        pFast = pFast->pNext;
    }
    while (pFast) {
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }
    return pSlow;
}

int GetCyleLen(struct ListNode* pMeetNode) //获得环长度
{
    int iLen = 1;
    struct ListNode* pNode = pMeetNode;
    if (NULL == pMeetNode) {
        return 0;
    }
    while (pNode->pNext != pMeetNode) {
        iLen++;
        pNode = pNode->pNext;
    }
    return iLen;
}

struct ListNode* HasCycle(struct ListNode* pHead) //判断链表是否有环
{
    struct ListNode* pSlow = pHead;
    struct ListNode* pFast = pHead;
    if (pHead == NULL) {
        return NULL;
    }
    while (pFast && pFast->pNext) {
        pSlow = pSlow->pNext;
        pFast = pFast->pNext->pNext;
        if (pSlow == pFast) {
            return pSlow;
        }
    }
    return NULL;
}

struct ListNode* MergeList(struct ListNode* pL1, struct ListNode* pL2) //合并两个单链表
{
    struct ListNode* pNewHead = NULL;
    struct ListNode* pL1Node = pL1;
    struct ListNode* pL2Node = pL2;
    struct ListNode* pNode = NULL;
    struct ListNode* pTailNode = NULL;
    if (pL1 == NULL) {
        return pL2;
    }
    if (pL2 == NULL) {
        return pL1;
    }
    
    if (pL1Node->data > pL2Node->data) {
        pNode = pL2Node;
        pL2Node = pL2Node->pNext;
    } else {
        pNode = pL1Node;
        pL1Node = pL1Node->pNext;
    }
    
    pNewHead = pNode;
    pTailNode = pNode;
    while (pL1Node && pL2Node) {
        if (pL1Node->data > pL2Node->data) {
            pNode = pL2Node;
            pL2Node = pL2Node->pNext;
        } else {
            pNode = pL1Node;
            pL1Node = pL1Node->pNext;
        }
        pTailNode->pNext = pNode;
        pTailNode = pTailNode->pNext;
    }
    
    if (pL1Node == NULL) {
        pTailNode->pNext = pL2Node;
    } else {
        pTailNode->pNext = pL1Node;
    }
    return pNewHead;
}

struct ListNode* FindEnterNode(struct ListNode* pHead, struct ListNode* pMeetNode)
{
    struct ListNode* pNode1 = pHead;
    struct ListNode* pNodeM = pMeetNode;
    if (pHead == NULL || pMeetNode == NULL) {
        return NULL;
    }
    while (pNode1 != pNodeM) {
        pNode1 = pNode1->pNext;
        pNodeM = pNodeM->pNext;
    }
    return pNode1;
}

int IsListCrose(struct ListNode* pL1, struct ListNode* pL2) //判断两个链表是否相交
{
    struct ListNode* pL1Node = pL1;
    struct ListNode* pL2Node = pL2;
    if (pL1 == NULL || pL2 == NULL) {
        return 0;
    }
    while (pL1Node->pNext != NULL) {
        pL1Node = pL1Node->pNext;
    }
    while (pL2Node->pNext != NULL) {
        pL2Node = pL2Node->pNext;
    }
    if (pL1Node == pL2Node) {
        return 1;
    }
    return 0;
}

int IsListCroseWithCycle(struct ListNode* pL1, struct ListNode* pL2) //判断两个带环链表是否相交
{
    struct ListNode* pL1MeetNode = NULL;
    struct ListNode* pL2MeetNode = NULL;
    struct ListNode* pL1Node = pL1;
    struct ListNode* pL2Node = pL2;
    if (pL1 == NULL || pL2 == NULL) {
        return 0;
    }
    pL1MeetNode = HasCycle(pL1);
    pL2MeetNode = HasCycle(pL2);
    // 两个都不带环
    if (pL1MeetNode == NULL && pL2MeetNode == NULL) {
        while (pL1Node->pNext != NULL) {
            pL1Node = pL1Node->pNext;
        }
        while (pL2Node->pNext != NULL) {
            pL2Node = pL2Node->pNext;
        }
        if (pL2Node == pL1Node) {
            return 1;
        }
        return 0;
    }
    // 两个都带环
    if (pL1MeetNode != NULL && pL2MeetNode != NULL) {
        struct ListNode* pNode = pL1MeetNode;
        while (pNode->pNext != pL1MeetNode) {
            if (pL2MeetNode == pNode) {
                return 1;
            }
            pNode = pNode->pNext;
        }
        // 假如 M1 和 M2 相连,M2 在 M1 前面时,在循环内 M2 无法检测到
        if (pNode == pL2MeetNode) {
            return 1;
        }
        return 0;
    }
    return 0;
}

main.c

#include "List.h"

#include <stdio.h>
#include <stdlib.h>

void TestPushBack()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PushBack(&pHead, 7);
    PrintList(pHead);
}
void TestPopBack()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PushBack(&pHead, 7);
    PrintList(pHead);
    
    PopBack(&pHead);
    PopBack(&pHead);
    PrintList(pHead);
}
void TestPushFront()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    
    PushFront(&pHead,6);
    PushFront(&pHead,7);
    PushFront(&pHead,8);
    PushFront(&pHead,9);
    PrintList(pHead);
    
}
void TestPopFront()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    
    PopFront(&pHead);
    PopFront(&pHead);
    PrintList(pHead);
}
void TestFind()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    
    struct ListNode* findNode = Find(pHead, 6);
    if (findNode != NULL) {
        printf("findNode address %p,data %d\n",findNode,findNode->data);
    } else {
        printf("not find!\n");
    }
    
}
void TestErase()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    struct ListNode* findNode = Find(pHead, 1);
    Erase(&pHead, findNode);
    PrintList(pHead);
}
void TestInsert()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    struct ListNode* findNode = Find(pHead, 2);
    
    Insert(&pHead, findNode, 6);
    PrintList(pHead);
}
void TestDestroyList()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    
    DestroyList(&pHead);
    PrintList(pHead);
}
void TestPrintListTailToHead()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    PrintListTailToHead(pHead);
}
void TestInsertNotHead()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    struct ListNode* findNode = Find(pHead, 2);
    InsertNotHead(findNode,6);
    PrintList(pHead);
}
void TestDelNotTailNode()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    struct ListNode* findNode = Find(pHead, 2);
    DelNotTailNode(findNode);
    PrintList(pHead);
}
void TestFindMidNode()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    struct ListNode* mid = FindMidNode(pHead);
    printf("mid data %d\n",mid->data);
    
    PushBack(&pHead, 6);
    mid = FindMidNode(pHead);
    printf("mid data %d\n",mid->data);
    
}
void TestJosephCircle()
{
    struct ListNode* pHead;
    struct ListNode* pTailNode = NULL;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PushBack(&pHead, 7);
    PrintList(pHead);
    pTailNode = Find(pHead, 7);
    pTailNode->pNext = pHead;
    pTailNode = JosephCircle(pHead, 2);
    free(pTailNode);
}

void TestReverseList()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PrintList(pHead);
    ReverseList(&pHead);
    PrintList(pHead);
}

void TestSortList()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 6);
    PushBack(&pHead, 4);
    PushBack(&pHead, 1);
    PushBack(&pHead, 9);
    PushBack(&pHead, 2);
    PushBack(&pHead, 7);
    PushBack(&pHead, 0);
    PushBack(&pHead, 3);
    PushBack(&pHead, 5);
    PushBack(&pHead, 8);
    PrintList(pHead);
    SortList(pHead);
    PrintList(pHead);
}

void TestFindLastKNode()
{
    struct ListNode* pHead;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PrintList(pHead);
    struct ListNode* lastK = FindLastKNode(pHead,2);
    printf("last K = %d\n",lastK->data);
}

void TestGetCyleLen()
{
    struct ListNode* pHead;
    struct ListNode* pos1;
    struct ListNode* pos2;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 7);
    PushBack(&pHead, 9);
    PrintList(pHead);
    /*---------构环---------*/
    pos1 = Find(pHead, 9);
    pos2 = Find(pHead, 5);
    pos1->pNext = pos2;
    /*---------------------*/
    int len = GetCyleLen(pos2);
    printf("cycle len = %d\n",len);
    
}

void TestHasCycle()
{
    struct ListNode* pHead;
    struct ListNode* pos1;
    struct ListNode* pos2;
    InitList(&pHead);
    PushBack(&pHead, 1);
    PushBack(&pHead, 2);
    PushBack(&pHead, 3);
    PushBack(&pHead, 4);
    PushBack(&pHead, 5);
    PushBack(&pHead, 6);
    PushBack(&pHead, 7);
    PushBack(&pHead, 9);
    PrintList(pHead);
    /*---------构环---------*/
    pos1 = Find(pHead, 9);
    pos2 = Find(pHead, 5);
    pos1->pNext = pos2;
    /*---------------------*/
    struct ListNode* pNode = HasCycle(pHead);
    if (pNode == NULL) {
        printf("list not cycle\n");
    } else {
        printf("list has cycle,pNode->data = %d\n",pNode->data);
    }
}

void TestMergeList()
{
    struct ListNode* pList1;
    struct ListNode* pList2;
    InitList(&pList1);
    PushBack(&pList1, 1);
    PushBack(&pList1, 3);
    PushBack(&pList1, 5);
    PushBack(&pList1, 7);
    PushBack(&pList1, 9);
    PrintList(pList1);
    
    InitList(&pList2);
    PushBack(&pList2, 2);
    PushBack(&pList2, 4);
    PushBack(&pList2, 6);
    PushBack(&pList2, 8);
    PrintList(pList2);
    struct ListNode* pList3 = MergeList(pList1, pList2);
    PrintList(pList3);
}

int main(int argc, const char * argv[])
{
    //TestPushBack();
    //TestPopBack();
    //TestPushFront();
    //TestPopFront();
    //TestFind();
    //TestErase();
    //TestInsert();
    //TestDestroyList();
    //TestPrintListTailToHead();
    //TestInsertNotHead();
    //TestDelNotTailNode();
    //TestFindMidNode();
    //TestJosephCircle();
    //TestReverseList();
    //TestSortList();
    //TestFindLastKNode();
    //TestGetCyleLen();
    //TestHasCycle();
    //TestMergeList();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值