1. 程式人生 > >二:單鏈表的反轉-遞迴和迴圈方式實現

二:單鏈表的反轉-遞迴和迴圈方式實現

/**
 * 通過遞迴方式實現單鏈表的反轉
 * 原來的單鏈表成為反轉後的單鏈表
 *
 * @param pList NODE_t * :帶頭結點的單鏈表的第一個有效結點
 */
NODE_t * SListRecur(NODE_t *pFirst) {
    if (pFirst == NULL || pFirst->pNext == NULL) {
        return pFirst;
    }

    NODE_t *pNewNode = SListRecur(pFirst->pNext);
    pFirst->pNext->pNext = pFirst;
    pFirst->pNext = NULL;
    return pNewNode;
}

NODE_t * ReverseSListRecur(NODE_t *pList) {
    if (pList == NULL || pList->pNext == NULL) {
        printf("single list is empty\n");
        return pList;
    }

    NODE_t *pHead = pList;
    NODE_t *pNewHead = SListRecur(pHead->pNext);
    pHead->pNext = pNewHead;
    return pHead;
}

/**
 * 通過迴圈方式實現單鏈表的反轉
 * 原來的單鏈表成為反轉後的單鏈表
 *
 * @param pList NODE_t * :單鏈表的頭結點
 */
NODE_t * ReverseSListCirle(NODE_t *pList) {
    if (pList == NULL || pList->pNext == NULL) {
        printf("single list is empty\n");
        return pList;
    }

    NODE_t *pHead = pList;
    NODE_t *pPre = pHead->pNext;
    NODE_t *pCur = pPre->pNext;
    NODE_t *pNext = NULL;
    /* 第一個有效結點的後繼不設定為空,會造成無限迴圈 */
    pPre->pNext = NULL;

    /* 使用三個指標指示當前,前一個,後一個結點地址
       每次使當前、前一個結點反轉,然後指標後移 */
    while (pCur != NULL) {
        pNext = pCur->pNext;
        pCur->pNext = pPre;
        pPre = pCur;
        pCur = pNext;
    }

    pHead->pNext = pPre;
    return pHead;
}


int main() {
    /* 建立單鏈表,遞迴遍歷單鏈表 */
    int aArray[6] = { 1, 4, 5, 2, 1, 6 };
    NODE_t *pList1 = CreateArraySList(aArray, 6);
    ShowSList(pList1);
    NODE_t *pNew1 = ReverseSListRecur(pList1);
    ShowSList(pNew1);
    FreeSList(pList1);

    /* 建立單鏈表,迴圈遍歷單鏈表 */
    NODE_t *pList2 = CreateArraySList(aArray, 6);
    ShowSList(pList2);
    NODE_t *pNew2 = ReverseSListCirle(pList2);
    ShowSList(pNew2);
    FreeSList(pList2);

    return 0;
}