單鏈表常見筆試面試題

定義一個結構體,用來表示鏈表上的每個節點的類型
typedef char LinkType

typedef struct LinkNode {
    LinkType data;
    struct LinkNode* next;
} LinkNode;

1)逆序打印單鏈表

使用低軌思想,遞歸出口 head == NULL

void LinkListReversePrint(LinkNode* head){
    if(head == NULL){
        return;
    }
    LinkListReversePrint(head->next);
    printf(" [%c|%p] ",head->data,head);
}

2)不允許遍歷鏈表,在pos之前插入

void LinkListInsertBefore(LinkNode** head, LinkNode* pos, LinkType value){
    if(head == NULL){
        return;
    }
    if(*head == NULL){
        return;
    }
    if(pos == NULL){
        return;
    }
    if(pos == *head){
        LinkListPushFront(head,value);
        return;
    }
    LinkNode* cur = *head;
    for(;cur != NULL;cur = cur->next){
        if(cur->next == pos){
            LinkNode* new_node = CreatNode(value);
            new_node->next = cur->next;
            cur->next = new_node;
            return;
        }
    }
}

3)約瑟夫環

LinkNode* LinkListJosephCircle(LinkNode** head,size_t value){
    if(head == NULL){
        //非法輸入
        return NULL;
    }
    if(*head == NULL){
        //空鏈表
        return NULL;
    }
    size_t i = 0;
    LinkNode* cur = *head;
    while(cur->next!=cur){
        for(i=1;i<value;++i){
            cur = cur->next;
        }
            printf("要刪除的節點是[%c]\n",cur->data);
            LinkNode* to_delete = cur->next;
            cur->data = to_delete->data;
            cur->next = to_delete->next;
            DestoryNode(to_delete);
    }
    return cur;
}

找到每次需要刪除的元素,同樣使用移花接木的思想,就不用去找當前元素的前節點位置

4)單鏈表逆置

void LinkListReverse(LinkNode** head){
    if(head == NULL){
        //非法輸入
        return;
    }
    if(*head == NULL){
        //空鏈表
        return;
    }
    LinkNode* pre = *head;
    LinkNode* cur = pre->next;
    while(cur!=NULL){
        LinkNode* tail = cur->next;
        cur->next = *head;
        pre->next = tail;
        *head = cur;
        cur = tail;
    }
}

5)單鏈表的冒泡排序

void LinkListBubblesort(LinkNode* head){
    if(head == NULL){
        return;
    }
    if(head->next == NULL){
        return;
    }
    LinkNode* tail = head;
    while(tail->next!=NULL){
        tail = tail->next;
    }
    LinkNode* cur = head;
    for(;cur->next!=NULL;cur = cur->next){
        LinkNode* n = head;
        for(;n->next!=tail;n=n->next){
            if(n->data > n->next->data){
                LinkType tmp = n->data;
                n->data = n->next->data;
                n->next->data = tmp;
            }
        }
            if(n->data > tail->data){
                LinkType tmp = n->data;
                n->data = tail->data;
                tail->data = tmp;
            }
            tail = n;
    }
}

6)將兩個有序鏈表合併爲一個有序鏈表

LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2){
    if(head1 == NULL && head2 == NULL){
            return NULL;
    }
    LinkNode* cur1 = head1;
    LinkNode* cur2 = head2;
    LinkNode* head;
    LinkNode* tail;
    if(head1->data < head2->data){
        head = cur1;
        tail = cur1;
        cur1=cur1->next;
    }else{
        head = cur2;
        tail = cur2;
        cur2=cur2->next;
    }
    while(cur1!=NULL && cur2!=NULL){
        if(cur1->data <cur2->data){
            tail->next = cur1;
            cur1 = cur1->next;
            tail = tail->next;
        }else{
            tail->next = cur2;
            cur2 = cur2->next;
            tail = tail->next;
        }
    }
    if(cur1 == NULL && cur2 != NULL){
        tail = cur2;
    }else if(cur1 != NULL && cur2 == NULL){
        tail = cur1;
    }
    return head;
}

7)找到鏈表中間的節點

LinkNode* FindMidNode(LinkNode* head){
    if(head == NULL){
        return NULL;
    }
    if(head->next == NULL){
        return head;
    }
    LinkNode* fast = head;
    LinkNode* slow = head;
//    size_t count = 0;
//    while(fast!=NULL){
//        count++;
//        fast = fast->next;
//    }
//    size_t m = count/2;
//    while(m--){
//        slow = slow->next;
//    }
//    return slow;
    while(slow->next != NULL & fast->next->next != NULL){
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

快慢指針的思想,快指針走兩步,慢指針走一步,快指針走到鏈表結尾,慢指針剛好走到中間

8)找到倒數第K個節點

LinkNode* FindLastKNode(LinkNode* head, size_t k){
    if(head == NULL){
        return NULL;
    }
    if(head->next == NULL){
        return head;
    }
    LinkNode* cur = head;
    size_t count = 0;
    while(cur!=NULL){
        ++count;
        cur = cur->next;
    }
    if(k<=0 && k>count){
        return NULL;
    }
    LinkNode* fast = head;
    LinkNode* slow = head;
    k = k-1;
    while(k--){
        fast = fast->next;
    }
    while(fast->next!=NULL){
        fast = fast->next;
        slow = slow->next;
    }
//    printf("[%c]\n",fast->data);
    return slow;
}

快慢指針,快指針走k步之後兩個指針在同時走,這樣快指針到了結尾,慢指針指到k個節點

9)刪除倒數第K個節點

void EraseLastKNode(LinkNode** head, size_t k){
    if(head == NULL){
        return;
    }
    if(*head == NULL){
        return;
    }
    LinkNode* cur = *head;
    size_t count = 0;
    while(cur!=NULL){
        ++count;
        cur = cur->next;
    }
    if(k<=0 && k>count)
        return;
//    if(head->next == NULL){
//        LinkListPopFront(head);
//    }
    printf("%lu\n",k);
    if(k==count){
        LinkListPopFront(head);
        return;
    }
    LinkNode* fast = *head;
    LinkNode* slow = *head;
    while(k--){
        fast = fast->next;
    }
    while(fast->next!=NULL){
        fast = fast->next;
        slow = slow->next;
    }
    LinkNode* to_delete = slow->next;
    slow->next = to_delete->next;
    DestoryNode(to_delete);
//    printf("[%c]\n",slow->data);
//    printf("[%c]\n",fast->data);

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章