链表相关内容

#include <iostream>
typedef struct node {
    int nVal;
    node* pNext;
    node(int val) : nVal(val), pNext(nullptr) {}
};

// create
node* create_link(int nNodeCnt, bool is_cycle=false) {
    if (nNodeCnt < 1) {
        std::cout << "fail to create node, node cnt error";
        return nullptr;
    }
    node* pHeader = new node(0);
    node* pCur = pHeader;
    for (int i=1; i < nNodeCnt; ++i) {
        node* pTmp = new node(i);
        pCur->pNext = pTmp;
        pCur = pCur->pNext;
    }
    if (is_cycle) {
        pCur->pNext = pHeader;
    }
    return pHeader;
}
// search
void search_display(node* pHeader, bool is_cycle=false) {
    node* pCur = pHeader;
    if (!is_cycle) {
        while(pCur) {
            std::cout << pCur->nVal << ",";
            pCur = pCur->pNext;
        }
        std::cout << "\n";
    } else {
        pCur = pHeader;
        std::cout << pCur->nVal << ",";
        pCur = pCur->pNext;
        while(pCur && pCur != pHeader) {
            std::cout << pCur->nVal << ",";
            pCur = pCur->pNext;
        }
        std::cout << "\n";
    }

}
// clear
void clear_link(node* pHeader, bool is_cycle=false) {
    node* pCur = pHeader;
    if (!is_cycle) {
        while (pCur) {
            node* pTmp = pCur;
            pCur = pCur->pNext;
            delete pTmp;
            pTmp = nullptr;
        }
    } else {
        // del first node
        pCur = pHeader;
        node* pPrev = pCur;
        pCur = pCur->pNext;
        delete pPrev;
        pPrev = nullptr;

        // del left nodes
        while (pCur && pCur != pHeader) {
            pPrev = pCur;
            pCur = pCur->pNext;
            delete pPrev;
            pPrev = nullptr;
        }
    }

}
// reverse whole link
node* reverse(node* pHeader) {
    if (nullptr == pHeader || nullptr == pHeader->pNext) {
        return pHeader;
    }
    node* pCur = pHeader;
    node* pLeft = nullptr;
    node* pRight = nullptr;
    while (pCur) {
        pRight = pCur->pNext;
        pCur->pNext = pLeft;
        pLeft = pCur;
        pCur = pRight;
    }
    return pLeft;
}
// reverse 【M,N】
node* reverse_M_N(node* pHeader, int M, int N) {
    if (M >= N) {
        return pHeader;
    }
    // cur pos
    node* pCur = pHeader;
    // first part tail
    node* pFirstTail = nullptr;
    node* pSecondTail = nullptr;
    // if start pos is the not first element
    if (M > 0) {
        // M - 1
        for (int i=0; i < M-1; ++i) {
            pCur = pCur->pNext;
        }
        // now pCur is at M-1, first part tail
        pFirstTail = pCur;
        // pCur is at M
        pCur = pCur->pNext;
        // second part tail
        pSecondTail = pCur;
    }

    // start to reverse
    node* pLeft = nullptr;
    node* pRight = pCur->pNext;
    int curPos = M;
    while (pCur && curPos <= N) {
        pRight = pCur->pNext;
        pCur->pNext = pLeft;
        pLeft = pCur;
        pCur = pRight;
        ++curPos;
    }

    // join three parts
    if (M==0) {
        pHeader->pNext = pCur;
        pHeader = pLeft;
        return pHeader;
    } else {
        pFirstTail->pNext = pLeft;
        pSecondTail->pNext = pCur;
        return pHeader;
    }
}
// reverse K groups
node* reverse_grp(node* pHeader, int nCntPerGrp) {
    // signle reverse
    if (nCntPerGrp == 1) {
        return reverse(pHeader);
    }
    // do not reverse
    if (nCntPerGrp == 0 || nullptr == pHeader) {
        return pHeader;
    }
    node* pCur = pHeader;
    int nTotalCnt = 0;
    // get total nodes cnt
    while (pCur) {
        ++nTotalCnt;
        pCur = pCur->pNext;
    }
    // total groups
    int nGrpsCnt = nTotalCnt / nCntPerGrp;
    // total count < nCntPerGrp, do not reverse
    if (nGrpsCnt == 0) {
        return pHeader;
    }
    // reset pCur
    pCur = pHeader;
    // the prev part tail
    node* pPrevTail = nullptr;
    // the cur part tail, will be assigned to the prev part tail in next while cycle
    node* pCurTail = pCur;

    // reverse by groups
    for (int i = 1; i <= nGrpsCnt; ++i) {
        node* pLeft = nullptr;
        node* pRight = nullptr;
        int tmpCnt = 1;
        pCurTail = pCur;
        while (pCur && tmpCnt <= nCntPerGrp) {
            pRight = pCur->pNext;
            pCur->pNext = pLeft;
            pLeft = pCur;
            pCur = pRight;
            ++tmpCnt;
        }
        // join cur part and prev part
        if (i==1) {
            // if this is the first groups, save the header
            pPrevTail = pHeader;
            pHeader = pLeft;
        } else {
            // join the prev tail node and cur header node
            pPrevTail->pNext = pLeft;
            // reset pPrevTail
            pPrevTail = pCurTail;
        }
    }
    // join the left part
    pCurTail->pNext = pCur;
    return pHeader;
}
// delete Kst node
node* del_K_node(node* pHeader, int K) {
    if (K <= 1) {
        node* pTmp = pHeader;
        pHeader = pHeader->pNext;
        delete pTmp;
        pTmp = nullptr;
    }
    node* pCur = pHeader;
    node* pTmp = pCur;
    int pos = 1;
    while (pCur) {
        if (pos == K - 1) {
            node* pTmp = pCur->pNext;
            pCur->pNext = pCur->pNext->pNext;
            delete pTmp;
            pTmp = nullptr;
            break;
        }
        pCur = pCur->pNext;
        ++pos;
    }
    return pHeader;
}
// delete K backward node
node* del_K_back_node(node* pHeader, int K) {
    node* pFast = pHeader;
    node* pSlow = pHeader;
    if (K <= 1) {
        K = 1;
    }
    int nCurCntFast = 1;
    for (; nCurCntFast <= K && pFast->pNext; ++nCurCntFast) {
        pFast = pFast->pNext;
    }
    // K > node cnt
    if (nCurCntFast < K) {
        return pHeader;
    }
    // K == node cnt, del header
    if (nCurCntFast == K) {
        node* pTmp = pHeader;
        pHeader = pHeader->pNext;
        delete pTmp;
        pTmp = nullptr;
        return pHeader;
    }
    // del middle element
    while (pFast->pNext && pSlow) {
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }
    // delete K
    node* pTmp = pSlow->pNext;
    pSlow->pNext = pSlow->pNext->pNext;
    delete pTmp;
    pTmp = nullptr;

    return pHeader;
}
// del mid node
node* del_middle_node(node* pHeader) {
    if (nullptr == pHeader->pNext) {
        return pHeader;
    }

    node* pFast = pHeader;
    node* pSlow = pHeader;
    node* pPrev = pHeader;
    while (pFast->pNext && pSlow) {
        if (pFast->pNext->pNext) {
            pFast = pFast->pNext->pNext;
            pPrev = pSlow;
            pSlow = pSlow->pNext;
        } else {
            pFast = pFast->pNext;
        }
    }
    if (pSlow == pHeader) {
        pHeader = pSlow->pNext;
    } else {
        pPrev->pNext = pPrev->pNext->pNext;
    }
    delete pSlow;
    pSlow = nullptr;
    return pHeader;
}
// josephus
node* show_jose_hus(node* pHeader, int total) {
    // when pos % 3 == 0 and cur_total > 1, del node
    int cur_total = total;
    int pos = 1;
    node* pCur = pHeader;
    node* pPrev = nullptr;
    while (pCur && cur_total > 1) {
        if (3 == pos) {
            // del cur
            pPrev->pNext = pPrev->pNext->pNext;
            node* pTmp = pCur;
            pPrev = pCur;
            pCur = pCur->pNext;
            std::cout << "del: " << pPrev->nVal << "\n";
            delete pTmp;
            pTmp = nullptr;
            pos = 1;
            --cur_total;
        } else {
            ++pos;
            pPrev = pCur;
            pCur = pCur->pNext;
        }

    }
    std::cout << "left one: " << pCur->nVal;
    return pCur;
}
// single link has circle and find first common node
// 快慢指针 当快慢指针相遇时, 慢指针走路程 * 2 = 快指针路程
// 当相遇时, 快指针从头出发, 步长修改为与慢指针一致, 当两者再次相遇时即为入口
node* get_link_first_common_node(node* pHeader, bool &has_cycle) {
    has_cycle = false;
    if (nullptr == pHeader) {
        return pHeader;
    }
    node* fast = pHeader;
    node* slow = pHeader;
    while (fast->pNext && fast->pNext->pNext && slow->pNext) {
        fast = fast->pNext->pNext;
        slow = slow->pNext;
        if (fast == slow) {
            has_cycle = true;
        }
    }
    return pHeader;
}
// two links encounter and find first common node
// 快慢指针, 快指针一次移动2个单位, 慢指针一次移动1个单位。移动的同时, 记录当前移动的节点个数。 M, N。当快指针的next = nullptr 时,
// 保持不动, 慢指针继续, 如果慢指针->next 在nullptr之前与快指针相等, 证明有重合点
// M - N能够知道长表与慢表的差值, 两个指针分别指向头部, 长表先移动M-N个单位。 然后两个指针一起移动, 当两个指针相等时, 即为重合点
// random node copy

// link dispart

int main() {
    std::cout << "Hello, World!" << std::endl;
    node* pHeader = create_link(10, false);
    //// origin link
    search_display(pHeader, false);
    //// reverse
    // pHeader = reverse(pHeader);
    //// reverse M_N
    // pHeader = reverse_M_N(pHeader, 4, 2);
    //// reverse by groups
    // pHeader = reverse_grp(pHeader, 4);
    //// del K node
    // pHeader = del_K_node(pHeader, 4);
    //// del K backward node
    //pHeader = del_K_back_node(pHeader, 6);
    //// del middle node
    // pHeader = del_middle_node(pHeader);
    //search_display(pHeader);
    //// josehus
    // pHeader = show_jose_hus(pHeader, 10);
    //// get single cycle first common node

    clear_link(pHeader, false);
    return 0;
}

  

posted on 2020-10-15 11:27  我是某某某是我  阅读(80)  评论(0编辑  收藏  举报

导航