数据结构与算法-链表

存储结构:

  数组是一块连续的内存空间存储的,然而链表是零散的内存空间存储的。

链表在插入和删除操作比数组高效,时间复杂度仅为O(1),链表不是使用连续的内存空间,所以可以充分利用零散的内存空间。

  链表结构:

         1. 单向链表

   2. 双向链表

现在最常见的链表结构:

    单向链表、双向链表,下面说一下这几种链表结构的实际操作

        1. 单向链表

            单向链表插入:找到节点a,在a节点插入节点x,先将x->next指向下一个节点a->next(c节点),再将a->next指向节点x。这里有一个点需要注意,不能先将a->next指向节点x,这样会丢掉节点c的。

    单向链表删除:找到节点b前一个节点a,将a->next指向b->next(c节点)

    单向链表查找:一个一个节点往下找

    实现代码:

template<class T>
struct ListNode {
    T data;
    ListNode<T>* pNext;
    ListNode() {
        pNext = NULL;
    }
};

template<class T>
class MyList {
public:
    MyList();
    ~MyList();
    void InsertListNode(T const& ,int const&);
    void DeleteListNode(int const&);
    void ReverseList();
    int SeachListNode(T const&) const;
    int GetListSize() const;
    ListNode<T>* GetListHeadNode() const;
protected:
    ListNode<T> *pHead;
private:
};

template<class T>
MyList<T>::MyList() {
    pHead = NULL;
}

template<class T>
MyList<T>::~MyList() {
    while(pHead != NULL) {
        ListNode<T>* pTmp = pHead;
        pHead = pHead->pNext;
        delete pHead;
    }
}

template<class T>
void MyList<T>::InsertListNode(T const& param, int const& nPosition) {
    if(nPosition > GetListSize() + 1) {
        return ;
    }
    ListNode<T>* pInsertNode = new ListNode<T>;
    pInsertNode->data = param;
    pInsertNode->pNext = NULL;
    //List empty
    if(pHead == NULL) {
        pHead = pInsertNode;
        return ;
    }
    int nP = nPosition;
    ListNode<T>* pCurrent = pHead;
    while(nP>1 && pCurrent->pNext != NULL) {    
        pCurrent = pCurrent->pNext;
        nP--;
    }
    pInsertNode->pNext = pCurrent->pNext;
    pCurrent->pNext = pInsertNode;
}

template<class T>
void MyList<T>::DeleteListNode(int const& nPosition) {
    if(pHead == NULL || nPosition > GetListSize()) {
        return ;
    }
    if(nPosition == 1) {
        ListNode<T>* pTmp = pHead;
        pHead = pHead->pNext;
        delete pTmp;
        return ;
    }
    int nP = nPosition;
    ListNode<T>* pLast = pHead;
    while(nP>2 && pLast->pNext != NULL) {
        pLast = pLast->pNext;
        nP--;
    }
    ListNode<T>* pCurrent = pLast->pNext;
    if(pCurrent != NULL) {
        pLast->pNext = pCurrent->pNext;
    }
    delete pCurrent;
}

template<class T>
int MyList<T>::SeachListNode(T const& param) const {
    int nPostion = 0;
    ListNode<T>* pTmp = pHead;
    while(pTmp) {
        nPostion++;
        if(pTmp->data == param) {
            return nPostion;
        }
        pTmp = pTmp->pNext;
    }
    return -1;
}

template<class T>
int MyList<T>::GetListSize() const {
    int nSize = 0;
    ListNode<T>* pTmp = pHead;
    while(pTmp != NULL) {
        nSize++;
        pTmp = pTmp->pNext;
    }
    return nSize;
}

template<class T>
ListNode<T>* MyList<T>::GetListHeadNode() const{
    return pHead;
}
View Code

  2.双向链表

            双向链表插入:找到节点a,在a节点插入节点x,先将x->next指向下一个节点a->next(b节点),x->prior指向节点a,b->prior指向节点x

    双向链表删除:找到节点b,b->prior(节点a)->next指向b->next(节点c),b->next(节点c)->prior指向b->prior(节点a)

    双向链表查找:一个一个节点往下找

实现代码:

 

template<class T>
struct DoubleListNode {
    T data;
    DoubleListNode<T>* pNext;
    DoubleListNode<T>* pPrior;
    DoubleListNode() {
        pNext = NULL;
        pPrior = NULL;
    }
};

template<class T>
class DoubleList {
public:
    DoubleList();
    ~DoubleList();
    void InsertDoubleListNode(T const& ,int const&);
    void DeleteDoubleListNode(int const&);
    void ReverseDoubleList();
    int SeachDoubleListNode(T const&) const;
    int GetDoubleListSize() const;
    DoubleListNode<T>* GetDoubleListHeadNode() const;
protected:
    DoubleListNode<T>* m_pHead;
private:
};

template<class T>
DoubleList<T>::DoubleList() {
    m_pHead = NULL;
}

template<class T>
DoubleList<T>::~DoubleList() {
    while(m_pHead != NULL) {
        DoubleListNode<T>* pTmp = m_pHead;
        m_pHead = m_pHead->pNext;
        delete pTmp;
    }
}

template<class T>
void DoubleList<T>::InsertDoubleListNode(T const& param, int const& nPosition) {
if(nPosition > GetDoubleListSize() + 1) {
        return ;
    }
    DoubleListNode<T>* pInsertNode = new DoubleListNode<T>;
    pInsertNode->data = param;
    pInsertNode->pNext = NULL;
    pInsertNode->pPrior = NULL;
    if(m_pHead == NULL) {
        m_pHead = pInsertNode;
        return ;
    }
    int nP = nPosition;
    DoubleListNode<T>* pCurrent = m_pHead;
    while(nP>1 && pCurrent->pNext != NULL) {
        pCurrent = pCurrent->pNext;
        nP--;
    }
    pInsertNode->pNext = pCurrent->pNext;
    if(pCurrent->pNext) {
        pCurrent->pNext->pPrior = pInsertNode;
    }
    pCurrent->pNext = pInsertNode;
    pInsertNode->pPrior = pCurrent;
}

template<class T>
void DoubleList<T>::DeleteDoubleListNode(int const& nPosition) {
    if(m_pHead == NULL || nPosition > GetDoubleListSize()) {
        return ;
    }
    if(nPosition == 1) {
        DoubleListNode<T>* pTmp = m_pHead;
        m_pHead = m_pHead->pNext;
        m_pHead->pPrior = NULL;
        delete pTmp;
        return ;
    }
    int nP = nPosition;
    DoubleListNode<T>* pCurrent = m_pHead;
    while(nP>1 && pCurrent != NULL) {
        pCurrent = pCurrent->pNext;
        nP--;
    }
    if(pCurrent != NULL) {
        DoubleListNode<T>* pLast = pCurrent->pPrior;
        pLast->pNext = pCurrent->pNext;
        pCurrent->pNext->pPrior = pLast;
    }
    delete pCurrent;
}

template<class T>
int DoubleList<T>::SeachDoubleListNode(T const& param) const {
    int nPostion = 0;
    DoubleListNode<T>* pTmp = m_pHead;
    while(pTmp) {
        nPostion++;
        if(pTmp->data == param) {
            return nPostion;
        }
        pTmp = pTmp->pNext;
    }
    return -1;
}

template<class T>
int DoubleList<T>::GetDoubleListSize() const {
    int nSize = 0;
    DoubleListNode<T>* pTmp = m_pHead;
    while(pTmp != NULL) {
        nSize++;
        pTmp = pTmp->pNext;
    }
    return nSize;
}

template<class T>
DoubleListNode<T>* DoubleList<T>::GetDoubleListHeadNode() const {
    return m_pHead;
}
View Code

可关注公众号了解更多的面试技巧

posted @ 2019-10-31 21:36  yew0  阅读(262)  评论(0编辑  收藏  举报