单链表的练习

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

顺序表

优点缺点
存储密度高容易浪费内存
随机存取节点插入删除效率低

单链表

优点缺点
插入删除效率高访问效率低
节点动内存利用率高

适用场景

顺序表单链表
数据量小,删除和插入工作量小的数据量大,删除和插入比较频繁的

2.从尾到头打印单链表
这个题采用递归的思想:

void  reverse_print(ListNode* pList)
{
    ListNode* tmp = pList;
    if (tmp == NULL)
    {
          return;
    }
    else
    {
        reverse_print(pList->next);
        printf("%d", tmp->data);
    }
}

3.删除一个无头单链表的非尾节点
采用替换法,可以将下一个节点的数据复制至已知节点,就有两个节点,然后删除后一个。

void  NoHeadList(ListNode** ppList)
{
    if ((*ppList)->next == NULL)
    {
        return;
    }
    ListNode* tmp = (*ppList)->next;
    (*ppList)->data = (*ppList)->next->data;
    (*ppList)->next = (*ppList)->next->next;
    free(tmp);
}

4.在无头单链表的一个节点前插入一个节点
与上一个题思路相同

void PushNoHaed(ListNode** ppList, DataType x)
{
    //创建新节点
    ListNode* node = (ListNode*)malloc(sizeof(ListNode));
    node->data = x;
    node->next = NULL;
    //已知节点复制
    node->next = (*ppList)->next;
    (*ppList)->next = node;
    node->data = (*ppList)->data;
    (*ppList)->data = x;
}

5.单链表实现约瑟夫环
循环删除第几个节点,直至剩下一个。

ListNode*  Josephus(ListNode* ppList, int x)
{
    ListNode* cru = ppList;

    while (cru != cru->next)
    {
        int count = x;
        while (--count)
        {
            cru = cru->next;
        }
        ListNode* next = cru->next;
        cru->data = next->data;
        cru->next = next->next;
        free(next);
    }
    return cru;
}

6.逆置/反转单链表

ListNode* ReverseList(ListNode* ppList)
{
    ListNode* NewHead = NULL;
    ListNode* cru = ppList;
    ListNode* p1 = ppList;
    while (cru)
    {
        cru = cru->next;
        p1->next=NewHead;
        NewHead = p1;
        p1 = cru;
    }
    return NewHead;
}

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

void Bubblsort(ListNode** pplist)
{
    ListNode* Tail = NULL;
    while (Tail!=(*pplist)->next)
    { 
        int count = 0;
        ListNode* slow = *pplist;
        ListNode* fast = slow->next;
        while (fast != Tail)
        {
            if (slow->data > fast->data)
            {
                DataType tmp = slow->data;
                slow->data = fast->data;
                fast->data = tmp;
                count++;
            }
            slow = fast;
            fast = slow->next;
        }
        Tail = slow;
        if (count == 0)
            break;
    }
}

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

ListNode* combineList(ListNode *p1, ListNode* p2)
{
    ListNode* NewList = NULL;
    ListNode* tmp = NULL;
    if (p1 == NULL)
        return p2;
    else if (p2 == NULL)
        return p1;
    else
    {
        if (p1->data<=p2->data)
        {
            NewList = p1;
            p1 = p1->next;
        }
        else
        {
            NewList = p2;
            p2 = p2->next;
        }
        tmp = NewList;
        while (p1&&p2)
        {
            if (p1->data > p2->data)
            {
                NewList->next = p1;
                p1 = p1->next;
                NewList = NewList->next;
            }
            else
            {
                NewList->next = p2;
                p2 = p2->next;
                NewList = NewList->next;
            }
        }
        if (p1 == NULL)
        {
            NewList->next = p2;
        }
        else
        {
            NewList->next = p1;
        }
    }
    return tmp;
}

9.查找单链表的中间节点,要求只能遍历一次链表
用两个指针,一个是另一个的二倍,当快指针到达最后,慢指针到达中间。

ListNode* Findmid(ListNode* pList)
{
    ListNode* slow = pList;
    ListNode* fast = pList;
    while (fast != NULL)
    {
        slow = slow->next;
        if (fast->next == NULL)
            break;
        fast = fast->next->next;
    }
    return slow;
}

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

ListNode* Findknode(ListNode* pList, int k)
{
    ListNode* slow = pList;
    ListNode* fast = pList;
    while (k--)
    {
        fast = fast->next;
    }
    while (fast != NULL)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值