C语言实现单链表面试题--基础篇

来源:互联网 发布:计算软件有哪些 编辑:程序博客网 时间:2024/06/04 18:27

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?

(1). 顺序表支持随机访问,单链表不支持随机访问。
(2). 顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)。
(3). 顺序表的CPU高速缓存效率更高,单链表CPU高速缓存效率低。

2.从尾到头打印单链表

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

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

void EraseNonTail(ListNode* pos){    assert(pos);    assert(pos->next);    ListNode* next = pos->next;    pos->data = next->data;    pos->next = next->next;    free(next);    next = NULL;}

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

void InsertNonTeal(ListNode *pos, DataType x){    assert(pos);    ListNode* newnode = BuyNode(x);    ListNode* next = pos->next;    pos->next = newnode;    newnode->next = next;    newnode->data = pos->data;    pos->data = x;}

5.单链表实现约瑟夫环
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
这里写图片描述

ListNode* JosepRing(ListNode* list, int k)//删除第K个结点,把这个结点的data改成下一个结点的data,然后删除第K个结点的下一个结点。{    if (!list)    {        return NULL;    }    ListNode* cur = list;    while (cur->next != cur)    {        int count = k;        while (--count)        {            cur = cur->next;        }        ListNode* next = cur->next;        cur->data = next->data;        free(next);    }    return cur;}

6.逆置/反转单链表

ListNode* Reverse(ListNode* list){    ListNode* newlist = NULL;    ListNode* cur = list;    while (cur)    {        //摘结点        ListNode* tmp = cur;        cur = cur->next;        //插结点        tmp->next = newlist;        newlist = tmp;    }    return newlist;}

7.单链表排序(冒泡排序)

void BubbleSort(ListNode* list){    ListNode* tail = NULL;    while (list->next != tail)    {        ListNode* cur = list;        ListNode* next = cur->next;        while (next != tail)        {            if (cur->data > next->data)            {                Datetype tmp = cur->data;                cur->data = next->data;                next->data = tmp;            }            cur = cur->next;            next = next->next;        }        tail = cur;    }}

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

ListNode* Merge(ListNode* list1, ListNode* list2){    if (!list1)    {        return list2;    }    if (!list2)    {        return list1;    }    //先找出两个链表中小的一个结点,把它摘下来做新链表的头结点    ListNode* list = NULL;    if (list1->data < list2->data)    {        list = list1;        list1 = list1->next;    }    else    {        list = list2;        list2 = list2->next;    }    //尾插    ListNode* 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)    {        tail->next = list2;    }    if (!list2)    {        tail->next = list1;    }    return list;}

9.查找单链表的中间节点,要求只能遍历一次链表
这里写图片描述

ListNode* FindMidNode(ListNode* list){    if (!list)    {        return NULL;    }    ListNode* slow = list;    ListNode* fast = list;    while (fast&&fast->next)    {        slow = slow->next;        fast = fast->next->next;    }    return slow;}

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

ListNode* FindTail_k_Node(ListNode* list,int K){    ListNode* slow = list;    ListNode* fast = list;    while (--K)    {        if (fast == NULL)//fast为空说明K值大于链表长度。既K值无效        {            return NULL;        }        fast = fast->next;    }    while (fast->next)    {        slow = slow->next;        fast = fast->next;    }    return slow;}
原创粉丝点击