单链表基础篇

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
1). 顺序表支持随机访问,单链表不支持随机访问。
2). 顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)。
3). 顺序表的CPU高速缓存效率更高,单链表CPU高速缓存效率低。
2.从尾到头打印单链表

//递归法
void PrintList(ListNode* plist)
{
    if(plist==NULL)
    {
        return;
    }
    PrintList(plist->next);
    printf("%d->",plist->data);
}

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

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

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

void InsertNonHead(ListNode* pos, DataType data)
{
    assert(pos);
    ListNode* next = pos->next;
    ListNode* tmp = BuyNode(data);
    pos->next = tmp;
    tmp->next = next;
    DataType datatmp = pos->data;
    pos->data = tmp->data;
    tmp->data = datatmp;
}

5.单链表实现约瑟夫环

ListNode* JosephRing(ListNode* plist, int k)
{
    //不带环返回空指针
    if(IsCycle(plist) == NULL)
    {
        return NULL;
    }

    ListNode* cur = plist;

    //只剩一个节点循环停止
    while(cur != cur->next)
    {
        int count = k;
        while(--count)  
        {
            cur = cur->next;
        }
        ListNode* next = cur->next;
        cur->data = next->data;
        cur->next = next->next;
        free(next);
    }
    return cur;
}

6.逆置/反转单链表

ListNode* ReverseList(ListNode* plist)
{
    ListNode* newhead = NULL;
    ListNode* cur = plist;
    ListNode* tmp = plist;

    while(cur)
    {
        cur = cur->next;
        tmp->next = newhead;
        newhead = tmp;
        tmp = cur;
    }

    return newhead;
}

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

void BubbleList(ListNode* plist)
{

    ListNode* tail = NULL;

    while(tail != plist->next)
    {
        ListNode* cur = plist;
        ListNode* next = plist->next;

        while(next != tail)
        {
            if(cur->data > next->data)
            {
                DataType tmp = cur->data;
                cur->data = next->data;
                next->data = tmp;
            }

            next = next->next;
            cur = cur->next;
        }
        tail = cur;
    }
}

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

ListNode* CombineList(ListNode* plist1, ListNode* plist2)
{
    ListNode* list = NULL;

    if(plist1 == NULL)
    {
        return plist2;
    }
    else if(plist2 == NULL)
    {
        return plist1;
    }
    else
    {
        if(plist1->data < plist2->data)
        {
            list = plist1;
            plist1 = plist1->next;
        }
        else
        {
            list = plist2;
            plist2 = plist2->next;
        }
        ListNode* tail = list;
        while (plist1 && plist2)
        {
            if(plist1->data < plist2->data)
            {
                tail->next = plist1;
                plist1 = plist1->next;
                tail = tail->next;
            }
            else
            {
                tail->next = plist2;
                plist2 = plist2->next;
                tail = tail->next;
            }
        }
        if(plist1 == NULL)
        {
            tail->next = plist2;
        }
        else
        {
            tail->next = plist1;
        }
    }
    return list;
}

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

ListNode* SearchListMid(ListNode* plist)
{
    ListNode* fast = plist;
    ListNode* slow = plist;

    while (fast && fast->next)
    {
        fast = (fast->next)->next;
        slow = slow->next;
    }

    return slow;
}

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

ListNode* SearchListK_r(ListNode* plist, int k)
{
    ListNode* fast = plist;
    ListNode* slow = plist;

    //fast往后走k-1步
    int i = k;
    for(i=0; i<k-1; i++)
    {
        fast = fast->next;
        //如果k大于了链表长度,返回空指针
        if(fast == NULL)
        {
            return NULL;
        }
    }

    //让fast走到最后一个节点
    while(fast->next)
    {
        fast = fast->next;
        slow = slow->next;
    }

    return slow
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章