[置顶] 剑指OFFER之链表篇

#include <stdio.h>
#include <malloc.h>
#include "jianzhioffer_list.h"

#define MAX_LIST_NODE 128

struct list_node *p_arr[MAX_LIST_NODE] = {NULL};

status init_list(struct list_node **head)
{
    int value = 0;
    struct list_node *p;
    struct list_node *rear; /* 便于尾部插入新创建的结点 */
    int i = 0;

    (*head) = NULL;

    printf("please input the value of the inserted node:");
    scanf("%d", &value);

    while (value != -999)
    {
        p = (struct list_node*)malloc(sizeof(struct list_node));
        p_arr[i++] = p; /* 存放链表指针的全局数组 */
        if (!p)
        {
            printf("%s: malloc failed\n", __FUNCTION__);
            return ERROR;
        }
        
        printf("p = 0x%8x\n", (unsigned int)p);

        p->data = value;

        if (!*head)
        {
            (*head) = p;
            (*head)->next = NULL;
            rear = p;
        }
        else
        {
            rear->next = p;
            p->next = NULL;
            rear = p;
        }

        printf("please input the value of the inserted node:");
        scanf("%d", &value);
    }

   return OK; 
}

/*             面试题5:从头到尾打印链表                  */
/* 1、注意递归是隐式栈,嵌套过深会导致栈溢出,最好用显式栈 */
void reverse_print_list(struct list_node *head)
{
    if  (head) //是if(head),不是while(head)
    {
        /* 注释的三句话可以去掉 */
        //if (head->next)
        //{
            reverse_print_list(head->next);
        //}

        printf("%d ", head->data);
    }
}

/* 面试题13:在O(1)时间删除链表结点 */
void delete_list_node(struct list_node **head, struct list_node *deleted)
{
    struct list_node *p;

    if (!head || deleted)
    {
        return;
    }

    if (*head == deleted) /* 删除结点为头结点 */
    {
        p = (*head)->next;
        free(deleted);
        (*head) = p;
    }
    else if (deleted->next) /* 删除结点非头结点,亦非尾结点 */
    {
        p = deleted->next;
        deleted->data = p->data;
        deleted->next = p->next;
        free(p);
        p = NULL;
    }
    else /* 删除节点为非头结点,是尾结点 */
    {
       p = *head; 
       while (p->next != deleted)
       {
           p = p->next;
       }

       p->next = NULL;
       free(deleted);
       deleted = NULL;
    }
}

/* 面试题15:求链表中倒数第k个结点 */
struct list_node* get_kth_list_node(struct list_node *head, int k)
{
    struct list_node *front;
    struct list_node *behind;
    int i;

    if (!head || (k <= 0))
    {
        return NULL; 
    }

    front = behind = head;

    for (i = 1; i < k; i++)
    {
        if (front->next)
        {
            front = front->next;
        }
        else
        {
            return NULL;
        }
    }

    while (front->next)
    {
        front = front->next;
        behind = behind->next;
    }

    return behind;
}

/* 面试题16:反转链表 */
void reverse_list(struct list_node* *head)
{
    struct list_node *p1;
    struct list_node *p2;
    struct list_node *p;

    if (!*head)
    {
        return;
    }

    p1 = *head;
    p2 = (*head)->next;

    while (p2)
    {
        p = p2->next;
        p2->next = p1;
        p1 = p2;
        p2 = p;
    }

    (*head)->next = NULL;
    *head = p1;
}

/* 面试题16:反转链表之递归:首先以第一个为一组,剩余为一组。然后递归地反转剩余,直到一个节点的next为空,*
 * 另外调用该函数的函数置原链表的第一个节点的next为空,不能在该函数中置NULL。                          */
struct list_node* reverse_list_recursive(struct list_node *cur, struct list_node* *head)
{
    struct list_node *tmp;

    /* 判断cur为空是第一次进入该函数时作判断, 后续只会判断cur->next */
    if (!cur || !cur->next)
    {
        *head = cur;
        return cur;
    }

    tmp = reverse_list_recursive(cur->next, head);
    tmp->next = cur;
    return cur;
}

/* 面试题17:合并两个递增的链表 */
struct list_node* merge_list(struct list_node *head1, struct list_node *head2)
{
    struct list_node *p1 = head1;
    struct list_node *p2 = head2;
    struct list_node *temp;
    struct list_node *head3; /* temp的next结点指向合并的第一个真正的结点 */
    struct list_node *p;

    if (!head1)
    {
        return head2;
    }

    else if (!head2)
    {
        return head1;
    }

    temp = (struct list_node*)malloc(sizeof(struct list_node));
    if (!temp)
    {
        printf("%s: malloc failed\n", __FUNCTION__);
        return NULL;
    }

    p = temp;
    p->next = NULL;
   
    while (p1 && p2)
    {
        if (p1->data <= p2->data)
        {
            p->next = p1;
            p = p->next;
            p1 = p1->next;
        }
        else
        {
            p->next = p2;
            p = p->next;
            p2 = p2->next;
        }
    }
/*
    if (!p1)
    {
        while (p2)
        {
            p->next = p2;
            p = p->next;
            p2 = p2->next;
        }
    }

    if (!p2)
    {
        while (p1)
        {
            p->next = p1;
            p = p->next;
            p1 = p1->next;
        }
    }
*/
    p->next = p1 ? p1: p2;
    
    head3 = temp->next;
    free(temp);

    return head3;
}

int get_list_len(struct list_node *head)
{
    int count = 0;

    while (head)
    {
        count++;
        head = head->next;
    }

    return count;
}


/* 面试题26:复杂链表的复制 */
#if 1 /* 该题只写出代码,不调试 */
struct list_node_complex 
{
    l_elemtype data;
    struct list_node_complex *next;
    struct list_node_complex *sibling;
};

void clone_node(struct list_node_complex *head)
{
    struct list_node_complex *cur = head;
    struct list_node_complex *clone;

    while (cur)
    {
        clone = (struct list_node_complex *)malloc(sizeof(struct list_node_complex));
        if (!clone)
        {
            printf("%s: malloc failed\n", __FUNCTION__);
            return;
        }

        clone->data = cur->data;
        clone->sibling = NULL;
        clone->next = cur->next;

        cur->next = clone;
        cur = cur->next;
    }
}

void clone_sibling(struct list_node_complex *head)
{
    struct list_node_complex *cur = head;
    struct list_node_complex *clone;

    while (cur)
    {
        clone = cur->next;
        if (clone->sibling)
        {
            clone->sibling = clone->sibling->next;
        }
        cur = clone->next;
    }
}

struct list_node_complex *separate(struct list_node_complex *head)
{
    struct list_node_complex *cur = head;
    struct list_node_complex *clone;
    struct list_node_complex *clone_head;

    if (cur)
    {
        clone = cur->next;
        clone_head = clone;

        cur->next = clone->next;
        cur = cur->next;
    }

    while (cur)
    {
        clone->next = cur->next;
        clone = clone->next;
        
        cur->next = clone->next;
        cur = cur->next;
    }

    return clone_head;

}

struct list_node_complex *clone(struct list_node_complex *head)
{
    clone_node(head);
    clone_sibling(head);

    return separate(head);
}

#endif

/* 面试题37:两个链表的第一个公共节点 */
struct list_node * get_first_common_node(struct list_node *head1, struct list_node *head2)
{
    int len1 = 0;
    int len2 = 0;
    int diff_len;
    struct list_node *p1;
    struct list_node *p2;
    int i;

    if (!head1 || !head2)
    {
        return NULL;
    }

    len1 = get_list_len(head1);
    len2 = get_list_len(head2);

    diff_len = len1 - len2;
    p1 = head1;
    p2 = head2;
    if (diff_len < 0)
    {
        p1 = head2;
        p2 = head1;
        diff_len = len2 - len1;
    }

    for (i = 1; i <= diff_len; i++)
    {
        p1 = p1->next;        
    }

    while (p1 && p2)
    {
        if (p1 == p2)
        {
            return p1;
        }
        else
        {
            p1 = p1->next;
            p2 = p2->next;
        }
    }

    return NULL;
}

void print_list(struct list_node *head) 
{
    while (head)
    {
        printf("addr(0x%8x) -> value(%d)\n", (unsigned int)head, (unsigned int)head->data);

        head = head->next;
    }
}

int main(void)
{
    struct list_node *head;
    struct list_node *head1;
    struct list_node *head2;
    struct list_node *merge_head;
    struct list_node *common_node;
    struct list_node *p;
    int i;
    int k;

    init_list(&head);

    print_list(head);

    struct list_node *first_node = reverse_list_recursive(head, &head);
    if (first_node)
    {
        first_node->next = NULL;
    }

    printf("\nreverse the list recursively\n");
    print_list(head);

#if 0
    printf("\nreverse output the list\n");
    reverse_print_list(head);

    printf("\ninput the deleted node's no:");
    scanf("%d", &i);
    delete_list_node(&head, p_arr[i]); 

    print_list(head);

    printf("\nreverse output the list\n");
    reverse_print_list(head);

    printf("\nplease input the reverse k value:");
    scanf("%d", &k);
    p = get_kth_list_node(head, k);
    if (p)
    {
        printf("output the reverse kth's addr:0x%8x, value:%d\n", p, p->data);
    }

    printf("\nreverse the list\n");
    reverse_list(&head);
    print_list(head);

#endif
#if 0
    printf("\n======= init head1 =======\n");
    init_list(&head1);
    printf("\n======= print head1 =======\n");
    print_list(head1);
    printf("\n======= init head2 =======\n");
    init_list(&head2);
    printf("\n======= print head2 =======\n");
    print_list(head2);

    printf("\n======= merge head1 && head2 =======\n");
    merge_head = merge_list(head1, head2);
    print_list(merge_head);
    printf("\n======= print head1 after merge =======\n");
    print_list(head1);
    printf("\n======= print head2 after merge =======\n");
    print_list(head2);

    printf("\n======= head1 && head2 first common node =======\n");
    common_node = get_first_common_node(head1, head2);
    if (common_node)
    {
        printf("common_node = 0x%8x, data = %d\n", common_node, common_node->data);
    }
#endif

    return 0;
}


你可能感兴趣的:([置顶] 剑指OFFER之链表篇)