單鏈表基礎篇

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章