1. 程式人生 > >【C++】連結串列的實現

【C++】連結串列的實現

1.定義

//單向
struct Node{
     int value;
     Node * next;
 };
 //雙向
struct DNode{
     int value;
     DNode * left;
     DNode * right;
 };

2.基本操作

(1)插入節點

//p節點後插入值為i的節點
void insertNode(Node *p, int i){
    Node* node = new Node;
    node->value = i;
    node->next = p->next;
    p-
>next = node; }

(2)刪除節點

void deleteNode(Node *p){
    p->value = p->next->value;
    p->next = p->next->next;
}

(3)反向遍歷連結串列

//1.stack
void printLinkedListReversinglyByStack(Node *head){
    stack<Node* > nodesStack;
    Node* pNode = head;
    //遍歷連結串列
    while (pNode !=
NULL) { nodesStack.push(pNode); pNode = pNode->next; } while (!nodesStack.empty()) { pNode=nodesStack.top(); printf("%d\t", pNode->value); nodesStack.pop(); } } //2.遞迴 void printLinkedListReversinglyRecursively(Node *head){ if (head!=NULL)
{ if (head->next!=NULL) { printLinkedListReversinglyRecursively(head->next); } printf("%d\t", head->value); } }

(4)找出中間節點

Node* findMidNode(Node* head){
    Node* slow = head;
    Node* fast = head;
    while (fast->next != 0&&fast->next->next!=0) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

(5)找出倒數k個節點

Node* findKNode(Node* head,int k){
    Node *temp1 = head;
    Node *temp2 = head;
    while (k-->0) {
        if(temp2 == NULL){
            return NULL;
        }
        temp2 =temp2->next;
    }
    while (temp2->next != NULL&&temp2->next->next!=NULL) {
        temp1 = temp1->next;
        temp2 = temp2->next->next;
    }
    return temp1;
}

(6)翻轉連結串列

Node * reverseLinkedList(Node* head,int k){
    Node *reversedHead = NULL;
    Node *pNode = head;
    Node *pre = NULL;
    while (pNode!=NULL) {
        if (pNode->next==NULL) {
            reversedHead = pNode;
        }
        Node* nxt = pNode->next;
        pNode->next = pre;
        pre=pNode;
        pNode=nxt;
    }
    return reversedHead;
}

(7)判斷是否相交
思路:

如果兩個連結串列相交,其形狀必為y形,而不可以能為x形,即兩條連結串列必有相同的尾節點。首先,計算得到兩個連結串列的長度:m,n,求得兩個連結串列長度之差distance=|m-n|,讓較長得那個連結串列事先走distance步,這樣,若是連結串列相交得話,二者指標必相撞,相撞點即為相交點。

Node* findCrosspoint(Node* l1, Node* l2){
    int m = getLinkedListLength(l1);
    int n = getLinkedListLength(l2);
    int distance=0;
    Node *temp1= l1;
    Node *temp2= l2;
    if (m>n) {
        distance = m - n;
        while (distance>0) {
            distance--;
            temp1=temp1->next;
        }
    } else{
        distance = n - m;
        while (distance>0) {
            distance--;
            temp2 = temp2->next;
        }
    }
    while(temp1!=temp2&&temp1->next!=NULL&&temp2->next!=NULL){
        temp1=temp1->next;
        temp2=temp2->next;
    }
    if(temp1 == temp2){
        return temp1;
    }
    return 0;
}

(8)判斷連結串列是否有環路,獲取連線點,計算環的長度

思路:

判斷是否有環:slow和fast,slow指標每次走一步,fast指標每次走兩步,若是連結串列有環,fast必能追上slow(相撞),若fast走到NULL,則不含有環。
判斷環的長度:在相撞點處,slow和fast繼續走,當再次相撞時,slow走了length步,fast走了2*length步,length即為環得長度。
環得連線點:slow和fast第一次碰撞點到環的連線點的距離=頭指標到環的連線點的距離,此式可以證明,詳見上面連結。

bool containLoop(Node* head){
    if (head==NULL) {
        return false;
    }
    Node* slow = head;
    Node* fast = head;
    while (slow!=fast&&fast->next!=NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    if (fast==NULL) {
        return false;
    }
    return true;
}

int getLoopLength(Node* head){
    if (head==NULL) {
        return 0;
    }
    Node* slow = head;
    Node* fast = head;
    while (slow!=fast&&fast->next!=NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    if (fast==NULL) {
        return 0;
    }
    //slow和fast首次相遇後,slow和fast繼續走
    //再次相遇時,即slow走了一圈,fast走了兩圈
    int length = 0;
    while (slow!=fast) {
        length++;
        slow = slow->next;
        fast = fast->next->next;
    }
    return length;
}

Node* getJoinpoit(Node* head){
    if (head==NULL) {
        return NULL;
    }
    Node* slow = head;
    Node* fast = head;
    while (slow!=fast&&fast->next!=NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    if (fast==NULL) {
        return NULL;
    }
    Node* fromhead = head;
    Node* fromcrashpoint = slow;

    while (fromcrashpoint!=fromhead) {
        fromhead = fromhead->next;
        fromcrashpoint = fromcrashpoint->next;
    }
    return fromhead;
}

(9)二叉樹和雙向連結串列的轉換

struct BinaryTreeNode{
    int value;
    BinaryTreeNode* left;
    BinaryTreeNode* right;
};

BinaryTreeNode* convertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInLast){
    if (pNode == NULL) {
        return NULL;
    }
    BinaryTreeNode *pCurrent = pNode;
    if (pCurrent->left != NULL) {
        convertNode(pCurrent->left, pLastNodeInLast);
    }

    pCurrent->left = *pLastNodeInLast;
    if (*pLastNodeInLast != NULL) {
        (*pLastNodeInLast)->right=pCurrent;
    }

    *pLastNodeInLast = pCurrent;
    if (pCurrent->right != NULL) {
        convertNode(pCurrent->right, pLastNodeInLast);
    }
    return NULL;
}

BinaryTreeNode* convertBTToDLL(BinaryTreeNode* root){
    BinaryTreeNode *pLastNodeInLast = NULL;
    convertNode(root, &pLastNodeInLast);
    BinaryTreeNode *pHeadOfList = pLastNodeInLast;
    while (pHeadOfList != NULL && pHeadOfList->left != NULL) {
        pHeadOfList = pHeadOfList->left;
    }
    return pHeadOfList;
}

參考連結