單鏈表(c語言版)

SList.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<malloc.h>

typedef int DataType ;
typedef struct Node
{
    DataType data;
    struct Node* next;
}Node, *PLinkList;
void InitList(PLinkList* pplist); //初始化
void PrintList(PLinkList* pplist);  //打印
int GetLength(PLinkList plist);//求長度
void PushBack(PLinkList* pplist, DataType x);//尾插
void PushFront(PLinkList* pplist, DataType x);//頭插
void PopFront(PLinkList* pplist);//頭刪
void PopBack(PLinkList* pplist);//尾刪
Node* Find(PLinkList plist, DataType x);
void Insert(PLinkList* pplist, Node * n, DataType x);
void InsertFrontNode(Node *n, DataType x);
void Reverse(PLinkList *pplist); // 翻轉
void sort(PLinkList *plist);//排序
void PrintTailToHead(PLinkList plist);

PLinkList _CreateNode(DataType x)
{
    PLinkList tmp = (PLinkList)malloc(sizeof(Node));
    tmp->data = x;
    tmp->next = NULL;
    return tmp;
}

void InitList(PLinkList* pplist)
{
    assert(pplist);
    *pplist = 0;
}
void PrintList(PLinkList* pplist)
{
    PLinkList begin = *pplist;
    assert(pplist);
    while (begin != NULL)
    {
        printf("%d->", begin->data);
        begin = begin->next;
    }
    printf("NULL\n");
}
void PushBack(PLinkList* pplist, DataType x)
{
    PLinkList tmp;
    PLinkList begin = *pplist;
    assert(pplist);
    if (*pplist == NULL)
    {
        *pplist = _CreateNode(x);
    }
    else
    {
        tmp = _CreateNode(x);
        while (begin->next != NULL)
        {
            begin = begin->next;
        }
        begin->next = tmp;
        tmp->next = NULL;
    }

}
void PushFront(PLinkList* pplist, DataType x)
{
    PLinkList tmp;
    assert(pplist);
    if (*pplist == NULL)
    {
        *pplist = _CreateNode(x);
    }
    else
    {
        tmp = _CreateNode(x);
        tmp->next = *pplist;
        *pplist = tmp;
    }
}
int GetLength(PLinkList plist)
{
    int count = 0;
    PLinkList begin = plist;
    assert(plist);
    while (begin != NULL)
    {
        begin = begin->next;
        count++;
    }
    return count;
}
void PopFront(PLinkList* pplist)
{
    PLinkList tmp;
    assert(pplist);
    if (*pplist == NULL)
    {
        printf("SList is empty\n");
        return;
    }
    else
    {
        tmp = *pplist;
        *pplist = (*pplist)->next;
        free(tmp);
    }
}
void PopBack(PLinkList* pplist)
{
    PLinkList prev = *pplist,end = *pplist;
    assert(pplist);
    if (*pplist == NULL)
    {
        printf("SList is empty\n");
        return;
    }
    else if ((*pplist)->next == NULL)//只有一個節點
    {
        free(*pplist);
        *pplist = NULL;
        printf("delet success\n");
        return;
    }
    else //有多個節點
    {
        while (end->next != NULL)
        {
            prev = end;
            end = end->next;
        }
        prev->next = NULL;
        free(end);
    }
}
Node* Find(PLinkList plist, DataType x)
{
    PLinkList begin = plist;
    assert(plist);
    if (plist == NULL)
    {
        printf("SList is empty\n");
        return begin;
    }
    else 
    {
        while (begin != NULL)
        {
            if (begin->data == x)
            {
                printf("find %d\n", x);
                return begin;
            }

            begin = begin->next;
        }
    }
    printf("not find %d\n", x);
    return NULL;
}

void Insert(PLinkList* pplist, Node * n, DataType x)
{
    PLinkList tmp;
    assert(pplist);
    if (*pplist == NULL)
    {
        *pplist = _CreateNode(x);
        return;
    }
    else
    {
        tmp = _CreateNode(x);
        tmp->next = n->next;
        n->next = tmp;
    }
}
void DelMidNode(Node* n)
{
    assert(n);
    if ( n == NULL)
    {
        printf("node is NULL\n");
        return;
    }
    else if (n->next == NULL)
    {
        printf("n is trail node\n");
    }
    else
    {
        Node* tmp = n->next;
        n->data = tmp->data;
        n->next = tmp->next;
        free(tmp);
    }
}
int Remove(PLinkList* pplist, Node * n)
{
    assert(pplist);

     if ((n->next) == NULL)
    {
         PopBack(pplist);
        return 0;
    }
     else
     {
         DelMidNode(n);
         return 0;
     }
}
void Erase(PLinkList* pplist, DataType x, int all)
{
    Node* ret = *pplist;
    assert(pplist);
    do
    {
         ret = Find(ret,x);
        if (ret != NULL)
        {
            Remove(pplist, ret);
        }
    } while (ret != 0 && all != 0);
   }

void InsertFrontNode(Node *n, DataType x)
{
    Node *tmp;
    assert(n);
    if (n == NULL)
    {
        printf("n is NULL\n");
        return;
    }
    else
    {
        tmp = _CreateNode(n->data);
        tmp->next = n->next;
        n->next = tmp;
        n->data = x;
    }
}

//逆置/反轉單鏈表
void Reverse(PLinkList *pplist)
{
    Node* NewHead = NULL;
    Node* begin = (*pplist)->next;
    assert(pplist);
    if (*pplist != NULL)
    {
        // 取第一個節點做新的頭結點
        NewHead = *pplist;
        NewHead->next = NULL;
    }
    while (begin != NULL)
    {
        // 取節點進行頭插
        Node* tmp = begin;
        begin = begin->next;
        tmp->next = NewHead;
        NewHead = tmp;
    }
    *pplist = NewHead;
}

//鏈表排序
void sort(PLinkList *pplist) 
{
    int count = 0;
    int exchange = 0;
    PLinkList tmp = *pplist;
    assert(pplist);
    if (*pplist == NULL)
    {
        printf("SList is empty\n");
        return;
    }
    else
    {
        while (count < GetLength(*pplist))
        {
            exchange = 0;
           while (tmp->next != NULL)
            {
               if (tmp->data > tmp->next->data)
                {

                   DataType x = tmp->data;
                   tmp->data = tmp->next->data;
                   tmp->next->data = x;
                   exchange = 1;
                }
                tmp = tmp->next;
            }
           if (exchange == 0)
           {
               return;
           }
            tmp = *pplist; //又從頭開始檢查
            count++;
        }
    }
}

//從尾到頭打印單鏈表
void PrintTailToHead(PLinkList pList)
{
    if(pList)
    {
        PrintTailToHead(pList->next); //遞歸調用
        printf("%d->", pList->data);
    }

}

//單鏈表實現約瑟夫環
void JosephCycle(PLinkList* ppList, int k)
{
    Node* begin = *ppList;
    assert(ppList);
    if (*ppList == NULL)
    {
        return;
    }
    else
    {
        while (1)
        {
            if (begin->next == begin) //只剩下一個節點
            {
                break;
            }
            Node* del = NULL;
            int x = k;
            while (--x)
            {
                begin = begin->next;
            }
            //應用刪除一個無頭無尾的中間節點的思想
            printf("delete node is %d\n", begin->data);
            begin->data = begin->next->data; 
            del = begin->next;
            begin->next = del->next;
            free(del);
        }
        *ppList = begin;
    }
}

//合併兩個有序鏈表,合併後依然有序
PLinkList Merge(PLinkList pList1, PLinkList pList2)
{
    PLinkList pList = pList1; //新的頭節點
    PLinkList end;
    assert(pList1);
    assert(pList2);
    if (pList1 == NULL)
    {
        return pList2;
    }
    if (pList2 == NULL)
    {
        return pList1;
    }
    if (pList1 == pList2)
    {
        return pList1;
    }
    //選擇一個小的作爲頭節點
    if (pList1->data < pList2->data)
    {
        pList = pList1;
        pList1 = pList1->next;
    }
    else
    {
        pList = pList2;
        pList2 = pList2->next;
    }
    end = pList; //鏈接下一個節點
    while (pList1 && pList2)
    {
        Node* tmp = NULL;
        if (pList1->data < pList2->data)
        {
            tmp = pList1;
            pList1 = pList1->next;
        }
        else
        {
            tmp = pList2;
            pList2 = pList2->next;
        }
        end->next = tmp;
        end = tmp;
    }
    if (pList1)
    {
        end->next = pList1;
    }
    if (pList2)
    {
        end->next = pList2;
    }
    return pList;
}

//查找單鏈表的中間節點,要求只能遍歷一次鏈表
Node* FindMidNode(PLinkList *ppList)
{
    PLinkList slow = *ppList;
    PLinkList fast = *ppList;
    assert(ppList);
    if (*ppList == NULL)
    {
        return NULL;
    }
    else
    {
        while (fast && fast->next)
        {
            fast = fast->next->next; //快指針一次走兩步
            slow = slow->next;      //慢指針一次走一步
        }
        printf("MidNode is %d\n", slow->data);
        return slow;
    }
}

//查找單鏈表的倒數第k個節點,要求只能遍歷一次鏈表
Node* FindKNode(PLinkList *ppList,DataType k)
{
    int x = k;
    PLinkList slow = *ppList;
    PLinkList fast = *ppList;
    assert(ppList);
    if (*ppList == NULL)
    {
        return NULL;
    }
    else
    {
        while (fast && x--) //快指針先走k步
        {
            fast = fast->next;
        }
        if (x > 0)//鏈表總共都沒有k個節點
        {
            return NULL;
        }
        while (fast)  //當快指針走到結尾慢指針走到倒數第k個節點
        {
            fast = fast->next;
            slow = slow->next;
        }
        printf("The last %d node is %d\n", k, slow->data);
        return slow;
    }
}

//判斷單鏈表是否帶環
bool IsCycle(PLinkList pList, PLinkList *ppMeetNode) 
{
    assert(pList);
    PLinkList slow = pList;
    PLinkList fast = pList;
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            *ppMeetNode = slow;
            return true;
        }
    }
    *ppMeetNode = NULL;
    return false;
}



main.cpp

#include"Slist.h"
void test()
{
    int ret;
    PLinkList plist;
    InitList(&plist);
    PushFront(&plist, 1);
    PushFront(&plist, 2);
    PushFront(&plist, 3);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PrintList(&plist);
    PopFront(&plist);
    PrintList(&plist);
    PopBack(&plist);
    PrintList(&plist);
    PopBack(&plist);
    PrintList(&plist);
    PopBack(&plist);
    Find(plist, 4);
    ret = GetLength(plist);
    printf("length= %d\n", ret);
}
void test2()
{
    PLinkList ret;
    PLinkList plist;

    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PrintList(&plist);
    ret = Find(plist, 1);
    if (ret != NULL)
    {
        Insert(&plist, ret, 10);
    }
    PrintList(&plist);
}
void test3()
{
    PLinkList ret;
    PLinkList plist;
    Node* no = NULL;
    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PrintList(&plist);
    ret = Find(plist, 3);
    DelMidNode(ret);
    PrintList(&plist);
    ret = Find(plist, 1);
    Remove(&plist, ret);
    PrintList(&plist);
}
void test4()
{
    PLinkList plist;
    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PushBack(&plist, 1);
    PushBack(&plist, 1);
    PushBack(&plist, 3);
    PrintList(&plist);
    Erase(&plist, 1, 0);
    PrintList(&plist);
    Erase(&plist, 1, 1);
    PrintList(&plist);
}
void test5()
{
    PLinkList plist,ret;
    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PrintList(&plist);
    ret = Find(plist, 2);
    InsertFrontNode(ret, 10);
    PrintList(&plist);
    Reverse(&plist);
    PrintList(&plist);
    PrintTailToHead(plist);
}
void test6()
{
    PLinkList plist;
    InitList(&plist);
    PushBack(&plist, 6);
    PushBack(&plist, 4);
    PushBack(&plist, 2);
    PushBack(&plist, 1);
    PushBack(&plist, 5);
    PushBack(&plist, 3);
    PrintList(&plist);
    sort(&plist);
    PrintList(&plist);
    PrintTailToHead(plist);
}
void test7()
{
    PLinkList plist,ret;
    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PushBack(&plist, 4);
    PushBack(&plist, 5);
    PushBack(&plist, 6);
    PrintList(&plist);
    //構建約瑟夫環
    ret = Find(plist, 6);
    ret->next = plist;
    JosephCycle(&ret, 3);

}
void test8()  
{
    PLinkList plist, plist1, plist2;
    InitList(&plist1);
    PushBack(&plist1, 1);
    PushBack(&plist1, 2);
    PushBack(&plist1, 4);
    PushBack(&plist1, 6);
    PushBack(&plist1, 9);
    PushBack(&plist1, 10);
    PrintList(&plist1);

    InitList(&plist2);
    PushBack(&plist2, 3);
    PushBack(&plist2, 5);
    PushBack(&plist2, 7);
    PushBack(&plist2, 8);
    PushBack(&plist2, 14);
    PushBack(&plist2, 17);
    PrintList(&plist2);
    plist = Merge(plist1, plist2);
    PrintList(&plist);
    FindMidNode(&plist);
    FindKNode(&plist, 4);
}
void test9()
{
    char *tag = NULL;
    Node* entry, *end, *pMeetNode;
    PLinkList plist;
    InitList(&plist);
    PushBack(&plist, 1);
    PushBack(&plist, 2);
    PushBack(&plist, 3);
    PushBack(&plist, 4);
    PushBack(&plist, 5);
    PushBack(&plist, 6);
    PrintList(&plist);
    entry = Find(plist, 4);
    end = Find(plist, 6);
    end->next = entry;
    *tag = IsCycle(plist, &pMeetNode);
    printf("Is Cycle %s\n",*tag);
}
int main()
{
    test9();
    getchar();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章