C:有空頭鏈表

#include <stdio.h>
#include <stdlib.h>

//結點結構體
struct Node
{
    int a;
    struct Node * pNext;
};

//鏈表頭尾指針
struct Node * g_pEnd = NULL;//這裏的null沒有意義,由於在主函數開始會直接給head和end申請地址,成爲空頭
struct Node * g_pHead = NULL;

void InitListHead();
struct Node * CreatNode(int a);
void AddListTail(int a);
void AddListHead(int a);
void ScanList();



int main()
{
    InitListHead();
    //操做
    //在這裏不能頭添加刪尾,緣由不清楚
    //之後熟練以前暫時都使用有空頭尾添加
    AddListTail(10);
    AddListTail(20);
    AddListTail(30);
    AddListTail(40);
    DeleteListRand(20);

    ScanList();
    system("Pause");
}


//空頭鏈表初始化
void InitListHead()
{
    //鏈表空頭
    g_pHead = (struct Node *)malloc(sizeof(struct Node)); //此時head是有地址的,成爲空頭
    g_pHead->pNext = NULL;
    g_pEnd = g_pHead;//剛開始的時候,end地址就是head地址,表示一個空頭結點
}

//鏈表首節點的建立
struct Node * CreatNode(int a)
{
    //建立一個結點
    struct Node *pTemp = (struct Node *)malloc(sizeof(struct Node));
    //結點成員賦值
    pTemp->a = a;
    pTemp->pNext = NULL;
    return pTemp;
}

//尾添加
void AddListTail(int a)
{
    struct Node *pTemp = CreatNode(a);
    //連接
    g_pEnd->pNext = pTemp;
    g_pEnd = pTemp;


}

//頭添加
void AddListHead(int a)
{
    struct Node *pTemp = CreatNode(a);

    //連接
    pTemp->pNext = g_pHead->pNext;
    g_pHead->pNext = pTemp;
}

//遍歷整個鏈表
void ScanList()
{
    struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
    while (pTemp)
    {
        printf("%d\n",pTemp->a);
        pTemp = pTemp->pNext;
    }
}


//查找指定結點,而且返回結點地址
struct Node * SelectNode(int index)
{
    struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
    while (pTemp)
    {
        if (index == pTemp->a)
        {
            return pTemp;
        }
        pTemp = pTemp->pNext;
    }
    return NULL;
}

//任意位置添加結點(根據鏈表中的某個值,在後面添加)
void AddListRank(int index, int a)
{
    //判斷鏈表有沒有東西
    if (NULL == g_pHead->pNext)
    {
        printf("鏈表無節點");
    }
    //找index結點
    struct Node *pTemp = SelectNode(index);
    if (NULL == pTemp)
    {
        printf("查無此結點\n");
    }

    //找到了,鏈接到指定位置
    struct Node * pNode = CreatNode(a);
    if (pNode == g_pEnd)
    {
        g_pEnd->pNext = pNode;
        g_pEnd = pNode;
    }
    else
    {
        pNode->pNext = pTemp->pNext;
        pTemp->pNext = pNode;函數

  //在這裏有瑕疵,若是插入的值不是g_pEnd,能夠不修改g_pEnd的值,可是若是插入的值就在g_pEnd,則應該將g_pEnd指針指向pNode指針

 /* if (NULL == NewNode->pNext)
    {
        g_pEnd = NewNode;
    }排序

 */
    }
}



//struct Node * Find(int index)
//{
//    int cnt = 0;
//    //判斷鏈表有沒有東西
//    if (NULL == g_pHead->pNext)
//    {
//        printf("鏈表無節點");
//    }
//    //找index結點
//    struct Node *pTemp = g_pHead;
//    while(pTemp)
//    {
//        pTemp = pTemp->pNext;
//        if (cnt == index)
//        {
//            return pTemp;
//        }
//        cnt++;
//    }
//}
//
//void AddListNum(int a, int index)
//{
//    struct Node * pNode = CreatNode(a);
//    struct Node * pTemp = Find(index);
//    if (pTemp == g_pEnd)
//    {
//        g_pEnd->pNext = pNode;
//        g_pEnd = pNode;
//    }
//    else
//    {
//        pNode->pNext = pTemp->pNext;
//        pTemp->pNext = pNode;
//    }
//}

//刪頭
void DeleteListHead()
{
    //判斷鏈表有沒有東西
    if (NULL == g_pHead->pNext)
    {
        printf("鏈表無頭");
        return;
    }
    struct Node * pTemp = g_pHead->pNext;
    //變頭
    g_pHead->pNext = g_pHead->pNext->pNext;
    //釋放
    free(pTemp);
}

//刪尾
void DeleteListTail()
{
    //判斷鏈表有沒有東西
    if (g_pHead->pNext == NULL)
    {
        printf("鏈表無尾");
        return;
    }it

  //這裏用了多個if 和一個else可能會形成混亂,建議if else 在else下再if else,確保正確
    //有一個結點
    if (g_pHead->pNext == g_pEnd)
    {
        free(g_pEnd);
        g_pHead->pNext = NULL;
        g_pEnd = g_pHead;
    }

    else
    {
        //找到尾結點的下一個
        struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
        while (pTemp)
        {
            if (g_pEnd == pTemp->pNext)
            {
                break;
            }
            pTemp = pTemp->pNext;
        }
        //pTemp是尾巴的前一個
        free(g_pEnd);
        //變新尾巴
        g_pEnd = pTemp;
        //尾巴下一個賦值空
        g_pEnd->pNext = NULL;

    }
}
//刪指定結點
void DeleteListRand(int a)
{
    //判斷鏈表有沒有東西
    if (NULL == g_pHead->pNext)
    {
        printf("鏈表無節點");
    }
    //找index結點
    struct Node *pTemp = SelectNode(a);
    if (NULL == pTemp)
    {
        printf("查無此結點\n");
    }
    //找到結點
    //頭,尾和中間
    //找到前一個結點
    //只有一個結點
    if (pTemp == g_pEnd)
    {
        DeleteListTail();
    }
    else
    {
        struct Node *pT = g_pHead;
        while (pT)
        {
            if(pTemp == pT->pNext)
            {
                break;
            }
        pT = pT->pNext;
        }
        //刪除
        pT->pNext = pTemp->pNext;
        //釋放
        free(pTemp);
    }

}


//釋放鏈表
void FreeList()
{
    struct Node * pTemp = g_pHead;
    while (pTemp != NULL)
    {
        struct Node *pT = pTemp;
        pTemp = pTemp->pNext;
        free(pT);
    }
    g_pHead = NULL;
    g_pEnd = NULL;
}

io

 //對鏈表進行排序List

void SortList()
{


    int i, j, t;
    struct Node * p = g_pHead->pNext;
    struct Node * q = p->pNext;
    while (p != NULL)
    {
        while (q != NULL)
        {
            if (p->a > q->a)
            {
                t = p->a;
                p->a = q->a;
                q->a = t;
            }
            q = q->pNext;
        }
        p = p->pNext;
        q = p; //關鍵,若是不加則q爲NULL,若是q = p->pNext,則當q指向NULL時,p指向NULL指向的下一個,程序崩潰
    }
}遍歷

刪除的思路都是:程序

  先找到刪除的結點的前一個結點,而後設pT = 刪除的結點,前一個結點的指向地址變爲刪除結點指向的地址,free掉pT鏈表

 

特殊狀況考慮:di

  刪頭:考慮找不到結點狀況;  考慮空鏈表 g_pHead->pNext == NULL;   不用考慮一個結點的狀況!!(由於直接free);  其他

  刪尾:考慮找不到結點狀況;  考慮空鏈表 g_pHead->pNext == NULL;  考慮只有一個結點 g_pHead->pNext == g_pEnd; (由於找不到那個結點前面的值);  其他

  刪指定:考慮找不到結點狀況;  考慮空鏈表 g_pHead->pNext == NULL;  考慮只有一個結點 g_pHead->pNext == g_pEnd; (由於找不到那個結點前面的值);  其他

相關文章
相關標籤/搜索