1. 程式人生 > >c語言實現簡單單鏈表

c語言實現簡單單鏈表

1.比較順序表和連結串列的優缺點,說說他們正在什麼場景下使用?
答:
對於順序表,無論是動態還是靜態,他們有都會死連續的儲存空間,在讀取時間效率上比較短,但在插入和刪除時會比較麻煩,需要不斷的遍歷去找到尾節點。
對於連結串列,因為是鏈式儲存。因此在需要的時候我們才在堆上進行開闢空間,連結串列對於插入刪除比較簡單,但是遍歷需要多次跳轉。
對於空間申請方式:
順序表,空間開闢是在順序表空間已滿時開闢,開闢次數較多時會出現較大的空間浪費。
對於連結串列,空間是針對單個節點的,不存在多餘的空間浪費。並且在碎片空間池的機制下,有效利用碎片空間。
所以,順序表一般用於查詢遍歷操作比較頻繁的情況下進行使用,連結串列則針對於資料刪除修改比較頻繁的資料使用。
2.從未到頭列印單鏈表

void PrintNodeTailToHead(ListNode *head)
{
    if (head)
    {
        while (head->next)
        {
            PrintNodeTailToHead(head->next);
        }
    }
    printf("%d->",head->data);
}

3.刪除一個無頭單鏈表的非尾節點

void DelNoTail(ListNode*plist)
{
    ListNode*del = plist->next;
    plist->
data = del->data; plist->next = del->next; free(plist); plist = NULL; }

4.在無頭單鏈表的一個節點前程插入一個節點

void Insert(ListNode** ppList, ListNode* pos, DataType x)
{
    if ((*ppList) == NULL)
    {
        *ppList = BuyNode(x);
    }
    else
    {
        ListNode *cur = BuyNode(x);
        cur->next
= pos->next; pos->next = cur; } }

5.單鏈表實現約瑟夫環

DataType JLink(ListNode**pplist)
{
    ListNode *cur = *pplist;
    while ((*pplist)->next)
    {
        ListNode *del = *pplist;
        del = (*pplist)->next->next->next;
        *pplist = del;
        free(del);
        del = NULL;
    }
    return (*pplist)->data;
}

6.逆置/ 反轉單鏈表

void _Reversre(ListNode*plist)//遞迴
{
    ListNode *cur = plist;
    ListNode *prev = plist;
    while (cur->next)
    {
        prev = cur;
        cur = cur->next;
    }
    cur->next = prev;
}
void reverse(ListNode**listhead)//非遞迴
{
    if ((NULL == (*listhead)) || (NULL == ((*listhead)->next)))
        return;  //邊界檢測  
    ListNode* ppre = *listhead;    //先前指標  
    ListNode* pcur = ppre->next;  //當前指標  
    ListNode* pnext = NULL;       //後繼指標  
    while (pcur != NULL)
    {
        pnext = pcur->next;
        pcur->next = ppre;
        ppre = pcur;
        pcur = pnext;
    }
    (*listhead)->next = NULL;
    (*listhead) = ppre;        //記錄下新的頭結點  
}

7.單鏈表排序(氣泡排序)

void sort(ListNode*plist)
{
    //冒泡
    ListNode *max=plist;
    DataType tmp;
    while (max->next)
    {
        if ((max->data) < plist->data)
        {
            tmp = max->data;
            max->data = plist->data;
            plist->data = tmp;
        }
        else
            plist = plist->next;
        if (plist->next == NULL)
        {
            max = max->next;
        }
    }
}

8.合併兩個有序連結串列,合併後依然有序

ListNode Merge(ListNode* head1, ListNode* head2)
{
    ListNode* newhead = NULL;
    if (head1->data < head2->data)
    {
        newhead = head1;
        head1 = head1->next;
        newhead->next = Merge(head1, head2);
    }
    if (head1->data>head2->data)
    {
        newhead = head2;
        newhead->next = Merge(head1, head2->next);
    }
}

9.查詢單鏈表的中間節點,要求只遍歷一遍

ListNode FindMid(ListNode*plist)
{
    ListNode *slow = plist;
    ListNode *fast = plist;
    while (fast)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return *slow;
}

10.查詢單鏈表的倒數第K個節點,要求只遍歷一遍

ListNode FindReNum(ListNode*plist, int k)
{
    ListNode*fast = plist;
    ListNode*slow = plist;
    while (k--)
    {
        fast=fast->next;
    }
    while (fast)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return *slow;