c语言实现单链表面试题(基础篇)

来源:互联网 发布:网络战略游戏 编辑:程序博客网 时间:2024/06/06 01:57

1.顺序便与单链表比较
顺序表:顺序表存储是将数据元素放到一块连续的内存储空间,相邻数据元素的存放地址也相邻,有动态存储和静态存储两种存储方式。
优点:(1)可以直接通过下标访问,支持随机访问,查找等效率较高。
(2)数据连续存放,空间利用率高,命中率高。
缺点:(1)当元素个数远小于预先分配的空间大小时,空间浪费比较严重;静态存储时,空间一经创建,大小不能改变,当需要存取的元素个数可能多于顺序表的元素个数时,会出现溢出问题。
(2)插入或删除数据效率较低,顺序表需要遍历移动元素。
链表:链表存储是程序运行过程中动态分配空间,相邻数据元素可任意存放,但所占存储空间分为两部分,一部分存放节点值,另一部分存放便是节点间关系的指针。
优点:(1)插入和删除效率较高,只需要改变指针指向即可。
(2)没有空间限制,只要存储器还有空间,就不会产生溢出问题。
缺点:(1)数据存放不连续,malloc开辟,空间碎片较多。
(2)查找速度较慢,当需要访问某个数据时,需要从第一个节点开始逐个查找。 适用场合:若线性表长度变化不大,且主要操作是查找很少插入删除时,可以采用顺序表;若线性表长度变化较大或者根本不知道多大,且其主要操作是插入删除很少查找时,可以采用链表,这样可以不用考虑存储空间大小问题。

//list.h

#include <stdio.h>#include <stdlib.h>#include <assert.h>#pragma oncetypedef int DataType;typedef struct ListNode{    DataType data;    struct ListNode* next;}ListNode;

2.从尾到头打印单链表

void PrintTailToHead(ListNode* ppHead){    if (ppHead == NULL)    {        return;    }    PrintTailToHead(ppHead->next);    printf("%d ", ppHead->data);}

3.删除一个无头单链表的非尾节点

void ErasenoTail(ListNode* pos){    ListNode* next;    assert(pos&&pos->next);    if (pos == -1)    {        return;    }    next = pos->next;    pos->data = next->data;    pos->next = next->next;    free(next);}

4.在无头单链表的一个节点前插入一个节点

void InsertnoTail(ListNode* pos,DataType x){     assert(pos);     if (pos == -1)     {         return;     }     ListNode* next= BuyNode(pos->data);     next->next = pos->next;     pos->next = next;     pos->data = x;}

5.单链表实现约瑟夫环

ListNode* Joseph(ListNode* hus, size_t k){    ListNode* man,*next;    assert(hus);    man = hus;    while (man->next != man)    {        size_t count = k;        while (--count)        {            man = man->next;        }        next = man->next;        man->data = next->data;        man->next = next->next;        free(next);    }    return man;}

6.逆置/反转单链表

void Reverse(ListNode** ppHead){    if (*ppHead == NULL)    {        return ;    }    else    {        ListNode* n0 = NULL, *n1 = *ppHead, *n2 = n1->next;        while (n1)        {            n1->next = n0;            n0 = n1;            n1 = n2;            if (n2)            {                n2 = n2->next;            }        }        *ppHead = n0;    }}

7.单链表排序(冒泡排序&快速排序)

void SortList(ListNode* pHead){    ListNode* tail = NULL;    if (pHead==NULL&&pHead->next==NULL)    {        return;    }    while (tail!=pHead)    {        int exchange = 0;        ListNode* cur = pHead, *next = cur->next;        while (next != tail)        {            if (cur->data > next->data)            {                exchange = 1;                DataType tmp = cur->data;                cur->data = next->data;                next->data = tmp;            }            cur = cur->next;            next = next->next;        }        if (exchange == 0)        {            break;        }        tail = cur;    }}

8.合并两个有序链表,合并后依然有序

ListNode* MergeList(ListNode* list1, ListNode* list2){    ListNode* list,*tail;    if (list1 == NULL)        return list2;    if (list2 == NULL)        return list1;    if (list1->data < list2->data)    {        list = list1;        list1 = list1->next;    }    else    {        list = list2;        list2 = list->next;    }    tail = list;    while (list1&&list2)    {        if (list1->data < list2->data)        {            tail->next = list1;            list1 = list1->next;        }        else        {            tail->next = list2;            list2 = list2->next;        }        tail = tail->next;    }    if (list1 != NULL)    {        tail->next = list1;    }    else    {        tail->next = list2;    }    return list;}

9.查找单链表的中间节点,要求只能遍历一次链表

ListNode* FindMidNode(ListNode* pHead){    ListNode* slow = pHead;    ListNode* fast = pHead;    while (fast && fast->next&&fast->next->next)    {        slow = slow->next;        fast = fast->next->next;    }    return slow;}

10.查找单链表的倒数第k个节点,要求只能遍历一次链表

ListNode* FindTailkNode(ListNode* pHead, size_t k){    ListNode* slow = pHead, *fast = pHead;    while (--k)    {        if (fast == NULL)        {            return NULL;        }        fast = fast->next;    }    while (fast->next)    {        slow = slow->next;        fast = fast->next;    }    return slow;}

//test.c

//Reverse/ErasenoTail/InsertnoTail/PrintTailToHeadvoid TestList1(){    ListNode* list = NULL;    PushBack(&list, 0);    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    PrintTailToHead(list);    Reverse(&list);    PrintList(list);    ErasenoTail(Find(list,2));    PrintList(list);    InsertnoTail(Find(list, 3),30);    InsertnoTail(Find(list, 2),40);    PrintList(list);}//Josephvoid TestList2(){    ListNode* tail;    ListNode* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    tail = Find(list, 5);    tail->next = list;    printf("live:%d\n", Joseph(list, 3)->data);}//SortListvoid TestList3(){    ListNode* list = NULL;    PushBack(&list, 5);    PushBack(&list, 3);    PushBack(&list, 2);    PushBack(&list, 7);    PushBack(&list, 9);    SortList(list);    PrintList(list);}//MergeListvoid TestList4(){    ListNode* list;    ListNode* list1 = NULL;    ListNode* list2= NULL;    PushBack(&list1, 1);    PushBack(&list1, 3);    PushBack(&list1, 5);    PushBack(&list1, 7);    PushBack(&list1, 9);    PushBack(&list2, 0);    PushBack(&list2, 2);    PushBack(&list2, 4);    PushBack(&list2, 6);    PushBack(&list2, 8);    list=MergeList(list1, list2);    PrintList(list);}//FindMidNode/FindTailkNodevoid TestList5(){    ListNode* list1=NULL;    PushBack(&list1, 0);    PushBack(&list1, 1);    PushBack(&list1, 3);    PushBack(&list1, 5);    PushBack(&list1, 7);    PushBack(&list1, 9);    SortList(list1);    printf("mid:%d\n", FindMidNode(list1)->data);    printf("tail k:%d\n", FindTailkNode(list1,3)->data);}#include test.hint main(){    TestList5();    system("pause");    return 0;}

“`

原创粉丝点击