带头节点控制单链表之C语言实现

//  1.头、尾节点位置
//  2.链表
//  元素数量
#include <stdio.h>
#include <stdlib.h>
#include <strings.h> 
#include <string.h>


//链表节点信息:
//
//   1.数据域
//   2.指针域


#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))


struct List_node;    //声明一个类型


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


//链表节点信息
typedef struct List_node
{
    int               data;    //数据域
    struct List_node *next;    //指针域
}List_node;


typedef unsigned char Boolean;


//  lua
//  C语言接口与实现   lcc


//链表的接口
List      *init_list(void)                        ;    //链表的初始化
void      destroy_list(List **list)               ;    //链表的销毁
Boolean   push_front(List *list, int value)       ;    //头部插入
Boolean   push_back(List  *list, int value)       ;    //尾部插入
Boolean   pop_front(List *list)                   ;    //头部删除
Boolean   pop_back(List *list)                    ;    //尾部删除
void      show_list(List *list)                   ;    //显示链表信息
void      sort_list_ascend(List *list)            ;    //升序排列
void      sort_list_descent(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)                    ;    //逆序输出链表信息
Boolean   is_list_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)的时间复杂度删除节点
Boolean has_circle(List *list, List_node **intersect)        ;   //判断一个链表是否有环
List_node *find_circle_first_node(List *list)              ;    //找到带环链表的环入口节点




static void *Malloc(size_t size);
static List_node *create_node(void); 
static void swap(void *a, void *b, int length);
static void rev_show_list(List_node *node);


static void swap(void *a, void *b, int length)
{
    void *temp = Malloc(length);
    memcpy(temp, a, length);
    memcpy(a, b, length);
    memcpy(b, temp, length);
    
    free(temp);
}


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, "the memory is full\n");
        exit(1);
    }
    return result;
}



//
// 链表接口实现
// 
//    链表控制信息
//    typedef struct List
//    {
//        struct List_node *head;    //指向链表头部
//        struct List_node *tail;    //指向链表尾部
//        int              count;    //链表节点数量
//    }List;
//    
//    //链表节点信息
//    typedef struct List_node
//    {
//        int               data;    //数据域
//        struct List_node *next;    //指针域
//    }List_node;
//









List      *init_list(void)                            //链表的初始化
{
    List *list = (List *)Malloc(sizeof(List));


    //      | head | tail | count |
    //          \      /      0
    //           \    /
    //            NULL
    bzero(list, sizeof(List));


    return list; 
}


void      destroy_list(List **list)                   //链表的销毁
{


    //              list
    //             /
    //         list_head  
    //          /
    //      | head | tail | count |
    //          \      \       n + 1
    //             
    //            \           \
    //            node->node2->node3
    if(list == NULL || *list == NULL){
        return ;
    }
   
    //  链表删除步骤:
    //  1.删除链表节点信息;
    while((*list)->count){   //头部删除链表节点
        pop_front(*list);
    }
    //  2.删除链表控制信息.
    free(*list);
    *list = NULL;
}


Boolean   push_front(List *list, int value)           //头部插入
{
    List_node *node = NULL;
  
    if(list == NULL){ 
        return FALSE;
    }   


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


    //   case1:
    //      | head | tail | count |
    //          \      /      1
    //           \    /
    //            node
    if(list->count == ZERO){
        list->tail = node;
    }else{
    //   case2:
    //      | head |              tail | count |
    //          \                 /       n + 1
    //           \               /
    //            node->node2->node3
        node->next = list->head;
    }
    list->head = node;
    list->count++;
    return TRUE;
}


Boolean   push_back(List  *list, int value)           //尾部插入
{
    List_node *node = NULL;


    if(list == NULL){
        return FALSE;
    }
  
    node = create_node();
    node->data = value;


    //   case1:
    //      | head | tail | count |
    //          \      /      1
    //           \    /
    //            node
    if(list->count == ZERO){
       list->head = list->tail = node;
    }else{
        //   case2:
        //      | head |              tail | count |
        //          \                 /       n + 1
        //           \               /
        //            node1->node2->node
        list->tail->next = node;
        list->tail = node;
    }
    list->count++;
    return TRUE;
}




Boolean   pop_front(List *list)                       //头部删除
{
    List_node *p_node = NULL;


    if(list == NULL || list->count == ZERO){
        return FALSE;
    }


    //   case1:
    //      | head | tail | count |
    //          \      /      1->0
    //           \    /
    //            node
    
    //   case2:
    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    p_node = list->head;
    if(list->count == ONLY_ONE){
        list->head = list->tail = NULL; 
    }else{
        list->head = list->head->next;
    }
    free(p_node);
    list->count--;
    return TRUE;
}


Boolean   pop_back(List *list)                        //尾部删除
{
    List_node *p_node = NULL;


    if(list == NULL || list->count == ZERO){ 
        return FALSE;
    }
   
    //   case1:
    //      | head | tail | count |
    //          \      /      1->0
    //           \    /
    //            node
    
    //   case2:
    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    p_node = list->head; 
    if(list->count == ONLY_ONE){    
        list->head = list->tail = NULL;
        free(p_node);
    }else{
        //判断倒数第二个?
        //   p_node->next == list->tail
        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)                       //显示链表信息
{
    List_node *p_node = NULL;


    if(list != NULL && list->count != ZERO){ 
        for(p_node = list->head; p_node; p_node = p_node->next){ 
            printf("%d ", p_node->data);
        }
        printf("\n");
    }
}


#if 1
void      sort_list_ascend(List *list)                //升序排列
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    unsigned long data_size = 0;


    if(list == NULL || list->count < TWO){
        return ;
    }
 // List_node *p = list->head;


 // p->next = NULL;


 // ((unsigned long)&(((List_node *)0)->next))


 // sizeof(List_node) - sizeof(List_node *);
 
   
    // int               data;  // 0   1   2   3
    //                          // 4   5   6   7
    // struct List_Node *next;  // 8   9  10  11
    //                            12  13  14  15
    //


    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_descent(List *list)               //降序排列
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    unsigned long data_size = 0;


    if(list == NULL || list->count < TWO){
        return ;
    }
 // List_node *p = list->head;


 // p->next = NULL;


 // ((unsigned long)&(((List_node *)0)->next))


 // sizeof(List_node) - sizeof(List_node *);
 
   
    // int               data;  // 0   1   2   3
    //                          // 4   5   6   7
    // struct List_Node *next;  // 8   9  10  11
    //                            12  13  14  15
    //


    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;
}


//   char *str1 = (char *)malloc(20);
//   strcpy(str1, "hello,world");
//
//   char *str2 = str1;
//   free(str1);
//
//   *str2  = 'c';


///
List      *merge_two_lists(List *list1, List *list2)    //合并两个有序链表
{
    List *result = NULL;
    List_node *list1_move = NULL;   
    List_node *list2_move = NULL;   
#if 0
    if(list1 == NULL){
        return result = copy_list_by_ctl(list2);
    }else if(list2 == NULL){
        return result = copy_list_by_ctl(list1);
    }
#endif
    if(list1 == NULL || list2 == NULL){
        return result;
    }


    result = init_list();   //结果链表得初始化


    list1_move = list1->head;
    list2_move = list2->head;


    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    //
    //
    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    //




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


    //当两个链表中任何一个遍历结束,则把另外一个进行尾部添加
    while(list2_move != NULL){
        push_back(result, list2_move->data);
        list2_move = list2_move->next;
    }


    while(list1_move != NULL){
        push_back(result, list1_move->data);
        list1_move = list1_move->next;
    }


    return result;
}


List      *merge_two_lists_recure(List *list1, List *list2);    //合并两个有序链表(递归)




List_node *find_revise_node(List *list, int num)   //找到链表的倒数第num个节点
{
    List_node *move = NULL;
    int move_count = 0;
    //     10   23   5   15    50    67   45   32  
    if(list == NULL || num <= 0 || num > list->count){
        return NULL;
    }    


    move = list->head;
    //移动的步长
    move_count = list->count - num;


    while(move_count--){
        move = move->next;
    }


    return move;
}




List_node *find_mid_node(List *list)    //找到链表的中间节点
{
    // 1. 快慢指针:
    //
    // f  每次移动2步, s 每次移动1步
    //     10   23  5  15  50  67  45  32  82
    //
    // 2. 8 / 2 = 4
    List_node *move = NULL;
    int move_count = 0;


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


    move = list->head;
    move_count = list->count >> 1;


    //   0000 1010   10
    //       10 >> 1
    //   0000 0101   5
    while(move_count--){
        move = move->next;
    }


    return move;
}


List      *reverse_list(List *list)    //逆置一个链表
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    List_node *m_node = NULL;




    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    if(list == NULL || list->count < TWO){
        return list;
    } 
    //两个节点
    if(list->count == TWO){
        list->tail->next = list->head;
        list->head->next = NULL;
    }else{    //三个节点
        p_node = list->head;
        q_node = p_node->next;
        m_node = q_node->next;
        p_node->next = NULL;
        do{
            q_node->next = p_node;   //让中间指针的next指向前一个
            p_node = q_node;    //指针整体向后搬移
            q_node = m_node;
            m_node = m_node->next;
        }while(m_node != NULL);
        q_node->next = p_node;
    }
    //交换头尾指针
    swap(&(list->head), &(list->tail), sizeof(List_node *));
    return list;
}


List      *list_dump(List *list)    //链表的拷贝
{


}


static void rev_show_list(List_node *node)
{
   //要打印当前节点,先打印其后续节点
   if(node != NULL){
       rev_show_list(node->next);
       printf("%d ", node->data);    
   }
}


void      reverse_show_list(List *list)    //逆序输出链表信息
{
    if(list == NULL || list->count == ZERO){
        return ;
    }  
    rev_show_list(list->head);
    printf("\n");
}


Boolean   is_list_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)    //得到第一个交点
{
    int list1_len = 0;
    int list2_len = 0;
    int distance = 0;
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    


    if(!is_list_intersect(list1, list2)){    //判断两个链表是否有交点
        return NULL;
    }
   
    list1_len = list1->count;
    list2_len = list2->count;


    p_node = list1->head;
    q_node = list2->head;


    //判断较长链表并首先进行移动
    if(list1_len >= list2_len){
      distance = list1_len - list2_len;
        while(distance--){ 
            p_node = p_node->next;
        }
    }else{
        distance = list2_len - list1_len;
        while(distance--){
            q_node = q_node->next;
        }
    }


    //依次对对应节点进行判断是否相等,如果相等则是第一个相交节点
    while(p_node != q_node){
        p_node = p_node->next;
        q_node = q_node->next;
    }
   
    return p_node;
}


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


    if(list == NULL || node == NULL){
        return ;
    }
 
    if(node != list->tail){    //不是最后一个节点
        p_node = node->next;
        node->data = p_node->data;
        node->next = p_node->next;
        free(p_node);
        list->count--;       
    }else{    //最后一个节点
        pop_back(list);
    }
}


Boolean has_circle(List *list, List_node **intersect)   //判断一个链表是否有环
{
    List_node *fast = NULL;
    List_node *slow = NULL;


    if(list == NULL || list->count < TWO){ 
        return FALSE;
    }


    fast = slow = list->head;   //两者都先指向头节点


    //定义两个指针,一快一慢,如果有环,则快指针先进入环
    //等慢指针进入后,两者最终会相遇
    while(fast != NULL && fast->next != NULL){
        fast = fast->next->next;
        slow = slow->next;


        if(fast == slow){   //两者在环中相遇
            if(intersect != NULL){
                *intersect = fast;
            }
            return TRUE;
        }
    }
    return FALSE;
}


List_node *find_circle_first_node(List *list)    //找到带环链表的环入口节点
{
    int list1_len = 0;
    int list2_len = 0;
    int distance = 0;
    List_node *intersect = NULL;
    List_node *list1_head = NULL;
    List_node *list2_head = NULL;
    List_node *p_node = NULL;
    List_node *q_node = NULL;


    if(!has_circle(list, &intersect)){
        return NULL;
    }


    //把问题转为求两个相交链表的第一个节点
    p_node = list1_head = list->head;
    q_node = list2_head = intersect->next;


    //统计两个链表的长度
    while(p_node != intersect){
        list1_len++;
        p_node = p_node->next;
    }


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


    p_node = list1_head;
    q_node = list2_head;


    //让较长链表先移动  |list1_len - list2_len| 步长
    if(list1_len >= list2_len)
  {
        distance = list1_len - list2_len;
        while(distance--){ 
            p_node = p_node->next;
        }
    }else{
        distance = list2_len - list1_len;
        while(distance--){
            q_node = q_node->next;
        }
    }
    
    while(p_node != q_node){
        p_node = p_node->next;
        q_node = q_node->next;
    }
   
    return p_node;
}


#endif
int main(int argc, char **argv)
{
    List *list1 = NULL;
    List *list2 = NULL;
    List *merge_list = NULL;
    List_node *middle = NULL;    //中间节点
    List_node *revise = NULL;    //倒数第n个节点


    int i = 0;


    list1 = init_list();   //链表初始化
    list2 = init_list();   //链表初始化


    for(i = 0; i < 10; ++i){
        push_back(list1, rand() % 200);
    }


    for(i = 0; i < 10; ++i){
        push_back(list2, rand() % 200);
    }


    show_list(list1);    //显示链表信息
    show_list(list2);   
    sort_list_ascend(list1);
    sort_list_ascend(list2);    


    merge_list = merge_two_lists(list1, list2);   //合并两个有序链表
    printf("list1 :");
    show_list(list1);    //显示链表信息
    printf("list2 :");
    show_list(list2);
    printf("merge list:\n");
    show_list(merge_list);


    middle = find_mid_node(merge_list);
    if(middle != NULL){
        printf("the mid of merge_list is:%d\n", middle->data);
    }


    revise = find_revise_node(merge_list, 5);
    if(middle != NULL){
        printf("the revise  of merge_list is:%d\n", revise->data);
    }


    reverse_list(merge_list);   //反转链表


    printf("reverse list :\n");
    show_list(merge_list);
     
    printf("merge_list revese show:\n");
    reverse_show_list(merge_list); 


    destroy_list(&list1);    //链表的销毁
    destroy_list(&list2);    //链表的销毁
    destroy_list(&merge_list);   
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值