【2015/11/21】 数据结构学习日志_Day17 双端链表

/*************************************************************************
    > File Name: ctr_list.c
    > Author: khalil
    > Mail: hsgwpj@gmail.com
    > Created Time: Sat 21 Nov 2015 09:11:34 AM CST
 ************************************************************************/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

// 《C语言接口与实现》 *
//  C的面向对象: lua
//  redis 键值对数据库

//比较优秀的网站:
//    stackoverflow
//    sourceforge

#if 1
//为bool类型宏定义
#define true     (1)
#define false    (0)

#define ZERO     (0)
#define ONLY_ONE (1)
#define TWO      (2)
#define get_data_size()  ((unsigned long)&(((List_node *)0)->next))

//链表控制信息:
//
// 1.头、尾节点位置
// 2.链表元素数量
//
//链表节点信息:
//
// 1.数据域
// 2.指针域

//节点:
typedef struct List_node
{
    int               data;     //数据域
    struct List_node *next;     //指针域
}List_node;

//控制:
typedef struct List
{
    struct List_node *head;     //指向链表头部
    struct List_node *tail;     //指向链表尾部
    int              count;     //链表节点数量
}List;

typedef unsigned char bool;

static void *Malloc(size_t size); //包裹函数
static List_node *create_node(void);//创建节点
static void swap(void *a, void *b, int len);//交换data
static void reverse_show_list_node(List_node *p);//组件

static void swap(void *a, void *b, int len)
{
    void *tmp = Malloc(len);
    memcpy(tmp, a, len);
    memcpy(a, b, len);
    memcpy(b, tmp, len);

    free(tmp);
}
static List_node *create_node(void)
{
    List_node *node = (List_node *)Malloc(sizeof(List_node));
    bzero(node, sizeof(List_node));
    return node;
}

static void *Malloc(size_t size)
{
    void *result = malloc(size);
    if(result == NULL){
        fprintf(stderr, "Memory Full!\n");
        exit(1);
    }
    return result;
}

static void reverse_show_list_node(List_node *p)
{
    if(p){
        reverse_show_list_node(p->next);
        printf("%d\t", p->data);
    }
}

//链表接口:
List        *init_list(void);                       //链表的初始化
void        destory_list(List **);                  //链表的销毁
bool        push_front(List *list, int value);      //头部插入
bool        push_back (List *list, int value);      //尾部插入
bool        pop_front (List *list);                 //头部删除
bool        pop_back  (List *list);                 //尾部删除
void        show_list (List *list);                 //显示链表信息
void        sort_list_ascend (List *list);          //升序排列
void        sort_list_descend(List *list);          //降序排列
int         get_list_count   (List *list);          //得到链表节点数量

//进阶

List        *merge_two_lists       (List *list1, List *list2);  //合并两个有序链表
List        *merge_two_lists_recure(List *list1, List *list2);  //合并两个有序链表(递归)
List_node   *find_revise_node(List *list, int num);             //找到链表的倒数第num个节点
List_node   *find_mid_node   (List *list);                      //找到链表的中间节点
List        *reverse_list    (List *list);                      //逆置一个链表
List        *list_dump       (List *list);                      //链表拷贝
void        reverse_show_list(List *list);                      //逆序输出一个链表
bool        is_lists_intersect    (List *list1, List *list2);   //判断链表是否相交
List_node   *get_first_common_node(List *list1, List *list2);   //得到第一个交点
void        delete_one_node       (List *List, List_node *node);//在O(1)的时间复杂度下删除节点
bool        has_circle            (List *list, List_node **intersect);                 //判断一个链表是否有环
List_node   *find_circle_first_node(List *list);                //找到带环链表的环入口点


//  接口实现  //


List        *init_list(void)                        //链表的初始化
{
    List *list = (List *)Malloc(sizeof(List));
    //    head && tail && count --> NULL/0
    bzero(list, sizeof(List));
    return list;
}

void        destory_list(List **list)                   //链表的销毁
{
    if(list == NULL || *list == NULL){
        return;
    }
    //遍历释放空间
        //List *p_list = *list;
        //List_node *p_node = p_list->head;
        //List_node *q_node = NULL;
        //删除链表节点信息
        //while(p_node){
        //    q_node = p_node;
        //    p_node = p_node->next;
        //    free(q_node);
        //}

    //删除链表节点信息
    while((*list)->count){
        pop_front(*list);
    }
    //删除链表控制信息
    free(*list);
    *list = NULL;
}

bool        push_front(List *list, int value)       //头部插入
{
    if(list == NULL){
        return false;
    }

    //创建节点并赋值
    List_node *node = create_node();
    node->data = value;

    if(list->count == ZERO){

        //  case 1:空链表
        //  head && tail -> node_1; count = 1

        list->head = list->tail = node;
    }else{

        // case 2:非空链表
        // head -> node_1 ; tail -> node_n; count = n + 1

        node->next = list->head;
        list->head = node;
    }
    list->count++;
    return true;
}

bool        push_back (List *list, int value)       //尾部插入
{
    if(list == NULL){
        return false;
    }

    List_node *node = create_node();
    node->data = value;

    if(list->count == ZERO){
        //case 1: 空链表
        list->head = list->tail = node;
    }else{
        //case 2: 非空链表
        list->tail->next = node;
        list->tail = node;
    }
    list->count++;
    return true;
}

bool        pop_front (List *list)                  //头部删除
{
    if(list == NULL || list->count == ZERO){
        return false;
    }

    List_node *p_node = list->head;

    //case 1:只有一个节点
    //case 2:大于一个节点

    if(list->count == ONLY_ONE){
        list->head = list->tail = NULL;
    }else{
        list->head = list->head->next;
    }
    free(p_node);
    list->count--;
    return true;
}

bool        pop_back  (List *list)                  //尾部删除
{
    if(list == NULL || list->count == ZERO){
        return false;
    }

    List_node *p_node = list->head;

    //case 1:只有一个节点
    //case 2:大于一个节点

    if(list->count == ONLY_ONE){
        list->head = list->tail = NULL;
        free(p_node);
    }else{
        //遍历一遍链表 将p_node指向倒数第二个节点
        while(p_node->next != list->tail){
            p_node = p_node->next;
        }
        free(list->tail);
        list->tail = p_node;
        p_node->next = NULL;
    }
    list->count--;
    return true;
}

void        show_list (List *list)                  //显示链表信息
{
    if(list != NULL && list->count != ZERO){
        List_node *p_node = list->head;
        for( ; p_node; p_node = p_node->next ){
            printf("%d\t",p_node->data);
        }
        printf("\n");
    }
}

void        sort_list_ascend (List *list)           //升序排列
{
    if(list == NULL || list->count < TWO){
        return ;
    }

    List_node *p_node = NULL;
    List_node *q_node = NULL;

    unsigned long data_size = 0;
    data_size = get_data_size();//求数据区域大小

    for(p_node = list->head; p_node->next; p_node = p_node->next){
        for(q_node = p_node->next; q_node; q_node = q_node->next){
            if(p_node->data > q_node->data){
                swap(p_node, q_node, data_size);
            }
        }
    }
}

void        sort_list_descend(List *list)           //降序排列
{
    if(list == NULL || list->count < TWO){
        return ;
    }

    List_node *p_node = NULL;
    List_node *q_node = NULL;

    unsigned long data_size = 0;
    data_size = get_data_size();//求数据区域大小

    for(p_node = list->head; p_node->next; p_node = p_node->next){
        for(q_node = p_node->next; q_node; q_node = q_node->next){
            if(p_node->data < q_node->data){
                swap(p_node, q_node, data_size);
            }
        }
    }
}

int         get_list_count   (List *list)           //得到链表节点数量
{
    if(list == NULL){
        return -1;
    }

    return list->count;
}

List        *merge_two_lists       (List *list1, List *list2)   //合并两个有序链表
{
    List *result = NULL;
    if(list1 == NULL || list2 == NULL){
        return result;
    }

    result = init_list();
    List_node *p = list1->head;
    List_node *q = list2->head;

    // 如果两个链表都没有遍历完,则进行比较
    while(p && q){
        if(p->data < q->data){
            push_back(result, p->data);
            p = p->next;
        }else{
            push_back(result, q->data);
            q = q->next;
        }
    }

    //如果有一个比较完了,把另一个直接进行拷贝
    if(p == NULL){
        while(q){
            push_back(result, q->data);
            q = q->next;
        }
    }
    if(q == NULL){
        while(p){
            push_back(result, p->data);
            p = p->next;
        }
    }

    return result;
}

List        *merge_two_lists_recure(List *list1, List *list2)   //合并两个有序链表(递归)
{
    //使用组件来进行递归输出!
}

List_node   *find_revise_node(List *list, int num)             //找到链表的倒数第num个节点
{
    if(list == NULL || num <= 0 && num > list->count){
        return NULL;
    }

    List_node *p = list->head;
    int time = list->count - num;

    while(time--){
        p = p->next;
    }

    return p;
}

List_node   *find_mid_node   (List *list)                      //找到链表的中间节点
{
    // 1.快慢指针:
    //  一个一次走两步 一个一次走一步
    //
    // 2.count/2找指针

    if(list == NULL){
        return NULL;
    }

#if 1
    List_node *p = list->head;
    List_node *q = p;

    while(p){
        p = p->next;
        if(p){
            p = p->next;
        }
        q = q->next;
    }

    return q;
#endif

#if 0
    List_node *p = list->head;
    int time = list->count >> 1;
    while(time--){
        p = p->next;
    }
    return p;
#endif
}

List        *reverse_list    (List *list)                     //逆置一个链表
{
    if(list == NULL || list->count < TWO){
        return list;
    }
#if 0
    //创建一个新的链表 与数组
    int datas[list->count];
    List_node *p = list->head;
    List *result = init_list();
    int i = 0;
    for( ; i < list->count; ++i ){
        datas[i] = p->data;
        p = p->next;
    }

    for( ; i; --i ){
        push_back(result, datas[i-1]);
    }
    return result;
#endif

#if 1
    //不创建新链表 使用三个指针进行赋值
    if(list->count == TWO){
        //如果只有两个节点
        list->tail->next = list->head;
        list->head->next = NULL;
        return list;
    }

    List_node *p = list->head;
    List_node *q = p->next;
    List_node *r = q->next;
    p->next = NULL;

    do{
        q->next = p;
        p = q;
        q = r;
        r = r->next;
    }while(r);

    q->next = p;

    swap(&(list->head), &(list->tail), sizeof(List_node *));
    return list;
#endif
}

List        *list_dump       (List *list)                      //链表拷贝
{
    if(list == NULL){
        return NULL;
    }

    List *result = init_list();
    List_node *p = list->head;

    while(p){
        push_back(result, p->data);
        p = p->next;
    }

    return result;
}

void        reverse_show_list(List *list)                      //逆序输出一个链表
{
    if(list == NULL){
        return;
    }
    //递归逆序输出比较好
    reverse_show_list_node(list->head);
    //使用组件来输出
}

bool        is_lists_intersect    (List *list1, List *list2)   //判断链表是否相交
{
    if (list1 == NULL || list2 == NULL){
        return false;
    }

    return (list1->tail == list2->tail);
}

List_node   *get_first_common_node(List *list1, List *list2)   //得到第一个交点
{
    if(! is_lists_intersect(list1, list2)){
        return NULL;
    }

    int list1_len = list1->count;
    int list2_len = list2->count;
    int distance  = 0;

    List_node *p = list1->head;
    List_node *q = list2->head;

    //将始末差距移动到相同距离
    if(list1_len > list2_len){
        distance = list1_len - list2_len;
        while(distance--){
            p = p->next;
        }
    }else{
        distance = list2_len - list1_len;
        while(distance--){
            q = q->next;
        }
    }

    //依次对对应节点进行判断是否相等,相等则为第一个相交界点
    while(p != q){
        p = p->next;
        q = q->next;
    }

    return p;
}

void        delete_one_node       (List *list, List_node *node)//在O(1)的时间复杂度下删除节点
{
    if(list == NULL || node == NULL){
        return ;
    }

    List_node *p = NULL;
    if(node != list->tail){
        //不是末尾
        p = node->next;
        node->data = p->data;
        node->next = p->next;
        free(p);
        list->count--;
    }else{
        //是末尾
        pop_back(list);
    }
}

bool        has_circle            (List *list, List_node **intersect)                 //判断一个链表是否有环
{
    if(list ==NULL || list->count < TWO){
        return false;
    }
    //快慢指针跑环
    //如果有环的话两者一定会相遇
    List_node *fast = list->head;
    List_node *slow = fast;

    do{
        fast = fast->next;
        fast = fast->next;
        slow = slow->next;
        if(fast == slow){
            if(intersect){
                //将相交节点赋值给intersect
                *intersect = fast;
            }
            return true;
        }
    }while(fast && fast->next);

    return false;
}

List_node   *find_circle_first_node(List *list)                //找到带环链表的环入口点
{
    List_node *intersect = NULL;
    if(! has_circle(list, &intersect)){
        return NULL;
    }

    //转化为求两个相交链表的第一个结点的问题
    List_node *list1_head = list->head;
    List_node *list2_head = intersect->next;

    //求得二个链表的长度
    List_node *p = list1_head;
    List_node *q = list2_head;

    int list1_len = 0;
    int list2_len = 0;
    int distance  = 0;

    while(p != intersect){
        list1_len++;
        p = p->next;
    }

    while(q != intersect){
        list2_len++;
        q = q->next;
    }

    p = list1_head;
    q = list2_head;

    //移动较长的链表 移动距离为两个长度的差
    if(list1_len > list2_len){
        distance = list1_len - list2_len;
        while(distance--){
            p = p->next;
        }
    }else{
        distance = list2_len - list1_len;
        while(distance--){
            q = q->next;
        }
    }

    while(p != q){
        p = p->next;
        q = q->next;
    }

    return q;
}

/// 测试 //

int main(int argc, char **argv)
{
    List* list = init_list();   //initialize
    List* list1 = init_list();
    List* tmp = NULL;
    int i = 0;
    for (i = 0; i < 10; ++i){
        push_back(list, rand() % 200);
        push_back(list1, rand() % 233);
    }
    printf("list:\n");
    sort_list_ascend(list);
    show_list(list);
    printf("list1:\n");
    sort_list_ascend(list1);
    show_list(list1);


    printf("\nmerge_result:\n");
    List* result = merge_two_lists(list, list1);
    show_list(result);

    List_node *p = find_revise_node(list, 1);
    printf("\nrevise_1_p:%d\n", p->data);

    List_node *mid = find_mid_node(list);
    printf("mid:%d\n", mid->data);

    reverse_list(list1);
    printf("reve:\n");
    show_list(list1);

    tmp = list_dump(list1);
    printf("copy:\n");
    show_list(tmp);
    printf("reve_show:\n");
    reverse_show_list(tmp);

    destory_list(&tmp);
    destory_list(&list);
    destory_list(&list1);
    destory_list(&result);
    return 0;
}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值