C语言实现单链表以及链表对应的面试题

来源:互联网 发布:centos查看php版本 编辑:程序博客网 时间:2024/06/06 09:43
//List.h#define _CRT_SECURE_NO_WARNINGS 1#ifndef __LIST_H__#define __LIST_H__#include<stdio.h>#include<stdlib.h>#include<assert.h>typedef int DataType;typedef struct Node    {    DataType data;    struct Node* next;}Node,*pNode,*pList;void InitList(pList* pplist); //初始化void PushBack(pList* pplist, DataType d); //尾插void PushFront(pList* pplist, DataType d);//头插void PopBack(pList* pplist);//尾删void PopFront(pList* pplist);//头删void show(pList plist);//输出int GetListLength(pList plist);//求链表的长度pNode Find(pList plist, DataType d);//查找void Remove(pList* pplist, DataType d);//删除第一个出现的dvoid RemoveAll(pList* pplist, DataType d);//删除链表所有dvoid Insert(pList*pplist, pNode pos, DataType d);//在节点前插入元素void Erase(pList* pplist, pNode pos);// 删除当前节点void DestroyList(pList *pplist);//销毁链表//链表面试题void EraseNotTail(pNode pos);  //删除一个无头非尾节点void InsertFrontNode(pNode pos, DataType d);  //在一个无头单链表的非头结点前插入一个元素void Reverselist(pList *pplist);    //将单链表逆序pList Merge(pList L1, pList L2);    //合并两个有序链表pList Merge2(pList L1, pList L2);    //合并两个有序链表pNode FindMidNode(pList list);        //查找链表中间节点void DelkNode(pList* pplist, int k);  //删除链表倒数第k的元素pNode JosephCycle(pList *pplist, int sum);   //约瑟夫环问题pNode CheckCycle(pList plist);    //检查是否带环int GetCycleLength(pNode meet);   //求环的长度pNode GetCycleEntryNode(pList plist, pNode meetNode);  //求环的入口地址void PrintReversely(pList plist);  //逆序打印单链表int CheckCross(pList list1, pList list2); //检查两个单链表是否相交#endif
//List.c#define _CRT_SECURE_NO_WARNINGS 1#include"List.h"void InitList(pList* pplist){    assert(pplist);    *pplist = NULL;}pNode BuyNode(DataType d){    pNode pnode = (pNode)malloc(sizeof(Node));    if (pnode == NULL)    {        perror("malloc");        return NULL;    }    pnode->data = d;    pnode->next = NULL;    return pnode;}void PushBack(pList* pplist, DataType d){    assert(pplist);    pNode NewNode = BuyNode(d);    if (*pplist == NULL)  //无节点    {        *pplist = NewNode;    }    else  //有节点    {        pNode cur = *pplist;        while (cur->next)        {            cur = cur->next;        }        cur->next = NewNode;    }}void PushFront(pList* pplist, DataType d){    assert(pplist);    pNode NewNode = BuyNode(d);    if (*pplist == NULL)//无节点    {        *pplist = NewNode;    }    else//有节点    {        NewNode->next = *pplist;        *pplist = NewNode;    }}void PopBack(pList* pplist){    pNode cur = *pplist;    pNode del = NULL;    assert(pplist);    if (*pplist == NULL)//无节点    {        printf("链表为空\n");        return;    }    else if (cur->next==NULL) //有一个节点    {        free(cur);        *pplist = NULL;    }    else //多个节点    {        while (cur->next)  //找倒数第二个元素        {            del = cur;            cur=cur->next;        }        free(cur);        del->next = NULL;    }}void PopFront(pList* pplist){    pNode cur = *pplist;    assert(pplist);    if (*pplist == NULL)//无节点    {        printf("链表为空\n");        return;    }    else if (cur->next == NULL)//有一个节点    {        free(cur);        *pplist = NULL;    }    else//多个节点    {        *pplist = cur->next;        free(cur);    }}void show(pList plist){    if (plist == NULL)    {        printf("链表为空\n");        return;    }    pNode cur = plist;    printf("list:");    while (cur)    {        printf("%d->", cur->data);        cur = cur->next;    }    printf("NULL\n");}int GetListLength(pList plist){    pNode cur = plist;    int count = 0;    while (cur)    {        cur = cur->next;        count++;    }    return count;}pNode Find(pList plist, DataType d){    pNode cur = plist;    while (cur)    {        if (cur->data == d)        {            return cur;        }        cur = cur->next;    }    return NULL;}void Remove(pList* pplist, DataType d)  //删除第一个出现的d{    assert(pplist);    pNode cur = *pplist;    pNode del = NULL;    while (cur)    {        if (cur->data == d)        {            if (*pplist == cur)            {                *pplist = cur->next;//要删除的是第一个节点            }            else            {                del->next = cur->next;//cur的上一个指向下一个            }            free(cur);             return;//这里必须结束不然下面del=cur;程序就会崩溃        }        del = cur; //作用保存cur上一个元素的地址        cur = cur->next;    }}void RemoveAll(pList* pplist, DataType d)//删除链表的所有d元素{    assert(pplist);    pNode cur = *pplist;    pNode tmp= NULL;    pNode del = NULL;    while (cur)    {        tmp = cur;//保存cur的地址        if (cur->data == d)        {            if (*pplist == cur)            {                *pplist = cur->next;//要删除的是第一个节点            }            else            {                del->next = cur->next;            }            cur = del;//删除后让cur保存cur上一个元素的地址            free(tmp);        }        del = cur;//作用保存cur上一个元素的地址        cur = cur->next;    }}void Insert(pList*pplist, pNode pos, DataType d){    assert(*pplist);    assert(pos);    pNode NewNode = BuyNode(d);    pNode cur = *pplist;    if (pos == cur)  //头节点    {        NewNode->next = *pplist;        *pplist = NewNode;    }    else    {        while (cur->next!=pos)//找到pos前一个节点        {            cur = cur->next;        }        NewNode->next = pos;        cur->next = NewNode;    }}void Erase(pList* pplist, pNode pos){    assert(pplist);    assert(pos);    pNode cur = *pplist;    pNode del = NULL;    //if (cur == NULL)    //{    //  printf("链表为空无法删除\n");    //  return;    //}    //if (cur == pos)  //头结点    //{    //  *pplist = cur->next;    //  free(cur);    //}    //else    //{    //  while (cur->next!=pos)    //  {    //      cur = cur->next;    //  }    //  cur->next = pos->next;    //  free(pos);    //}    if (pos->next == NULL)    {        PopBack(pplist);        return NULL;    }    pos->data = pos->next->data;//相当于删除下个元素把下一个元素的值给pos    del = pos->next;//del保存下个元素的地址    pos->next = pos->next->next;    free(del);}void DestroyList(pList *pplist){    pNode cur = *pplist;    while (cur)    {        pNode del = cur;        cur = cur->next;        free(del);    }    *pplist = NULL;}void EraseNotTail(pNode pos) //删除一个无头非尾节点{    assert(pos->next);    pNode cur = pos->next;    pos->data = pos->next->data;    pos ->next = pos->next->next;    free(cur);}void InsertFrontNode(pNode pos, DataType d) //在一个无头单链表的非头结点前插入一个元素{    pNode NewNode = BuyNode(d);    DataType tmp = 0;    NewNode->next = pos->next;//将元素插入pos后边    pos->next = NewNode;    tmp = pos->data; //然后将pos的值和d相交换    pos->data = NewNode->data;    NewNode->data = tmp;}void Reverselist(pList *pplist) //将单链表逆序{    assert(pplist);    pNode cur = *pplist;    pNode tmp = NULL;    pList NewList = NULL;    while (cur)    {        tmp = cur;        cur = cur->next;        tmp->next = NewList;        NewList = tmp;    }    *pplist = NewList;}pList Merge(pList L1, pList L2)    //合并两个有序链表{    pList NewList = NULL;    pNode tail = NULL;    if (L1 == L2)//如果两个相等返回任意一个    {        return L1;    }    if (L1 == NULL)//一个为空 返回另一个    {        return L2;    }    if (L2 == NULL)    {        return L1;    }    if (L1->data <= L2->data) //头结点    {        NewList = L1;        L1 = L1->next;    }    else    {        NewList = L2;        L2 = L2->next;    }    tail = NewList;    while (L1&&L2)     {        if (L1->data <= L2->data)        {            tail->next = L1;            tail = L1;            L1 = L1->next;        }        else        {            tail->next = L2;            tail = L2;            L2 = L2->next;        }    }    if (L1 == NULL)    {        tail->next = L2;    }    if (L2 == NULL)    {        tail->next = L1;    }    return NewList;}pList Merge2(pList L1, pList L2)    //合并两个有序链表采用递归调用{    pList NewList = NULL;    if (L1 == L2)    {        return L1;    }    if (L1 == NULL)    {        return L2;    }    if (L2 == NULL)    {        return L1;    }    if (L1->data <= L2->data)    {        NewList = L1;        NewList->next = Merge2(L1->next, L2);    }    else    {        NewList = L2;        NewList->next = Merge2(L2->next, L1);    }    return NewList;}pNode FindMidNode(pList list)        //查找链表中间节点{    pNode fast = list; //快指针    pNode slow = list;  //慢指针    while (fast&&fast->next)    {        slow = slow->next;        fast = fast->next->next;    }    return slow;}void DelkNode(pList* pplist, int k)  //删除链表倒数第k的元素{    assert(pplist);    pNode fast = *pplist;//快指针    pNode slow = *pplist; //慢指针    while (fast)    {        k--;        if (k < 0)        {            slow = slow->next;        }        fast = fast->next; //让快指针多走k步    }//然后当快指针下一个为空时慢指针刚好指向倒数第k的元素    pNode cur = slow->next;    slow->data = cur->data;     slow->next = cur->next;    free(cur);}pNode JosephCycle(pList *pplist, int sum)   //约瑟夫环问题{    assert(pplist);    int i = 0;    pNode cur = *pplist;    while ((cur->next) != cur)    {        if (cur->next == cur)        {            break;        }        for (i = 0; i < sum-1; i++)        {            cur = cur->next;        }        printf("%d ", cur->data);        pNode del = cur->next;        cur->data = cur->next->data;        cur->next = cur->next->next;        free(del);    }    return cur;}pNode CheckCycle(pList plist)    //检查是否带环{    pNode fast = plist;    pNode slow = plist;    while (fast&&fast->next)    {        fast = fast->next->next;//快指针走两步        slow = slow->next;//慢指针走一步        if (fast == slow)        {            return slow;// 当快慢相遇就返回这个元素地址        }    }    return NULL;}int GetCycleLength(pNode meet)   //求环的长度{    int count = 0;    pNode cur = meet;    do    {        cur = cur->next;        ++count;    } while (cur != meet);    return count;}pNode GetCycleEntryNode(pList plist, pNode meetNode) //求环的入口地址{    pNode cur = plist;    while (cur != meetNode)    {        cur = cur->next;        meetNode = meetNode->next;    }    return cur;}void PrintReversely(pList plist)  //逆序打印单链表{    pNode cur = plist;    if (plist == NULL)    {        return ;    }    if (cur != NULL)  //递归调用    {        PrintReversely(cur->next);    }    printf("%d ", cur->data);}int CheckCross(pList list1, pList list2) //检查两个单链表是否相交{    pNode cur1 = list1;    pNode cur2 = list2;    if (cur1==NULL||cur2==NULL)    {        return 0;    }    while (cur1)    {        cur1 = cur1->next;    }    while (cur2)    {        cur2 = cur2->next;    }    if (cur1 == cur2)        return 1;    return 0;}
Test.c#define _CRT_SECURE_NO_WARNINGS 1#include"List.h"//测试尾插以及尾删void test1(){    pList list = NULL;    InitList(&list);    PushBack(&list, 2);    PushBack(&list, 4);    PushBack(&list, 5);    PushBack(&list, 7);    PopBack(&list);    PopBack(&list);    PopBack(&list);    PopBack(&list);    PopBack(&list);}//测试头插以及头删void test2(){    pList list = NULL;    InitList(&list);    PushFront(&list, 1);    PushFront(&list, 2);    PushFront(&list, 3);    PushFront(&list, 4);    PushFront(&list, 5);    PopFront(&list);    PopFront(&list);    PopFront(&list);    PopFront(&list);    PopFront(&list);    PopFront(&list);}//测试输出以及链表长度void test3(){    pList list = NULL;    InitList(&list);    PushFront(&list, 1);    PushFront(&list, 2);    PushFront(&list, 3);    PushFront(&list, 4);    PushFront(&list, 5);    int ret = GetListLength(list);    printf("%d\n", ret);    show(list);}//测试Remove RemoveAllvoid test4(){    pList list = NULL;    InitList(&list);    PushBack(&list, 2);    PushBack(&list, 4);    PushBack(&list, 5);    PushBack(&list, 8);    PushBack(&list, 5);    PushBack(&list, 5);    PushBack(&list, 7);    PushBack(&list, 6);    show(list);    Remove(&list, 5);    show(list);    RemoveAll(&list, 5);    show(list);}//测试合并两个有序链表void TestMerge(){    pList list = NULL;    pList List = NULL;    pList NewList = NULL;    InitList(&list);    InitList(&List);    InitList(&NewList);    PushBack(&list, 2);    PushBack(&list, 4);    PushBack(&list, 5);    PushBack(&list, 7);    PushBack(&List, 1);    PushBack(&List, 3);    PushBack(&List, 5);    PushBack(&List, 8);    show(list);    show(List);    NewList = Merge2(list, List);    show(NewList);    pNode cur = NULL;    cur = FindMidNode(NewList);    printf("%d", cur->data);}//测试约瑟夫环问题void TestJosephCycle(){    pList list = NULL;    InitList(&list);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    Find(list, 5)->next = Find(list, 1);    pNode ret=JosephCycle(&list, 3);    printf("%d\n", ret->data);}//测试链表长度void TestGetCycleLength(){    pList list = NULL;    InitList(&list);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    Find(list, 5)->next = Find(list, 1);    pNode ret = CheckCycle(list);    int tmp = GetCycleLength(ret);    printf("%d\n", tmp);}//测试检查是否带环void TestCheckCycle(){    pList list = NULL;    InitList(&list);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    //Find(list, 5)->next = Find(list, 3);    pNode ret = CheckCycle(list);    if (ret == NULL)    {        printf("不带环\n");    }    else    {        printf("%d\n", ret->data);    }}//测试环的入口地址void TestGetCycleEntryNode(){    pList list = NULL;    InitList(&list);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PushBack(&list, 6);    PushBack(&list, 7);    PushBack(&list, 8);    Find(list, 8)->next = Find(list, 3);    pNode ret = CheckCycle(list);    pNode tmp = GetCycleEntryNode(list, ret);    printf("%d\n", tmp->data);}//测试逆序打印单链表void TestPrintReversely(){    pList list = NULL;    InitList(&list);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintReversely(list);}//测试两个单链表是否相交void TestCheckCross(){    pList list = NULL;    pList List = NULL;    InitList(&list);    InitList(&List);    PushBack(&list, 2);    PushBack(&list, 4);    PushBack(&list, 5);    PushBack(&list, 7);    PushBack(&List, 1);    PushBack(&List, 3);    PushBack(&List, 5);    PushBack(&List, 8);    Find(List, 8)->next = Find(list, 5);    show(list);    show(List);    int ret = CheckCross(list, List);    if (ret == 1)    {        printf("相交\n");    }    if (ret == 0)    {        printf("不相交\n");    }}int main(){    //test1();    //test2();    //test3();    test4();    //TestMerge();    //TestList();    //TestJosephCycle();    //TestCheckCycle();    //TestGetCycleLength();    //TestGetCycleEntryNode();    //TestCheckCross();    //TestPrintReversely();    //TestComplexList();    return 0;}
0 0
原创粉丝点击