数据结构之单链表的实现

单链表:

特点: 链表的链接方向是单向的;
链表是由节点构成,每个节点由两部分(节点数据和指向下一节点的指针);

>
链表的结构体及变量重定义如下:

#ifndef LIST_H_
#define LIST_H_

#define ONE  1
#define ZERO 0
#define TWO  2
//const int TRUE = 1;
//const int FALSE = 0;
enum BOOL {
    FALSE,
    TRUE
};

typedef unsigned char Boolean;

//定义连表的控制节点
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)                                      ;  //链表的初始化
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 print_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_node *find_revise_node(List *list, int num)           ;  //找到连表倒数第num个节点
List_node *find_middle_node(List *list)                    ;  //得到链表的中间节点
List *reverse_list(List *list)                             ;  //逆置链表
List *copy_list(List *list)                                ;  //链表的拷贝
Boolean is_list_intersect(List *list1, List *list2)        ;  //判断两个链表是否有交点
List_node *find_first_common_node(List *list1, List *list2);  //找到两个链表的第一个交点
void delete_one_node(List *list, List_node *node)          ;  //删除链表的一个节点
Boolean has_circle(List *list)                             ;  //判断链表是否有环
List_node *find_circle_begin(List *list)                   ;  //找到链表环的入口

链表的接口实现

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include "list.h"  //""当前目录查找头文件  <>在标准库中找


static void *Malloc(size_t size);
static List_node *create_node(void);

static List_node *create_node(void)
{
    List_node *node = NULL;

    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 mmemory is full!\n");
        exit(1);
    }

    return result;
}

List *init_list(void)                                        //链表的初始化
{
    List *list = NULL;
    list = (List *)Malloc(sizeof(List));
    bzero(list, sizeof(List));  //对申请的内存进行初始化(清空)

    return list;
}

void destroy_list(List **list)                               //连表的销毁
{
    //销毁步骤:(1)销毁链表节点
    //          (2)销毁控制信息
    //          (3)指针置为空
    if(list == NULL || *list == NULL){
        return ;
    }

    while((*list)->count){
        pop_front(*list);
    }

    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;

    //两种情况:1.链表数目为空
    if(list->count){
        node->next = list->head;
        list->head = node;
    }else{   //2.node既是head也是tail
        list->head = list->tail = 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;

    if(list->count){
        list->tail->next = node;
        list->tail = node;
    }else{
        list->head = 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;
    }

    p_node = list->head;

    if(list->count == ONE){
        list->head = list->tail = NULL;
    }else{
        list->head = p_node->next;
    }

    free(p_node);
    p_node = NULL;
    list->count--;

    return TRUE;
}

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

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

    p_node = list->head;

    if(list->count == ONE){
        list->head = list->tail = NULL;
        free(p_node);
    }else{
        while(p_node->next != list->tail){
            p_node = p_node->next;
        }
        free(list->tail);
        list->tail = p_node;
        p_node = NULL;
    }

    list->count--;

    return TRUE;
}

void print_list(List *list)                                  //打印链表
{
    List_node *p_node = NULL;

    if(list == NULL || list->count <= ZERO){
        return ;
    }
    p_node = list->head;

    while(p_node != NULL){
        printf("%d ", p_node->data);
        p_node = p_node->next;
    }

    printf("\n");
}

static void swap(void *a, void *b, int length);
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);
}
void sort_list_ascend(List *list)                            //升序排列连表
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;

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

    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->data, &q_node->data, sizeof(int));
            }
        }
    }
}

void sort_list_descend(List *list)                           //降序
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;

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

    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->data, &q_node->data, sizeof(int));
            }
        }
    }
}

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

    return list->count;
}



List *merge_two_lists(List *list1, List *list2)              //合并两个连表
{
    List *list3 = NULL;
    List_node *p_node = NULL;
    List_node *q_node = NULL;

    if(list1 == NULL && list2 == NULL){
        return list3;
    }

    list3 = init_list();

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

    while(p_node != NULL && q_node != NULL){
        if(p_node->data <= q_node->data){
            push_back(list3, p_node->data);
            p_node = p_node->next;
        }else{
            push_back(list3, q_node->data);
            q_node = q_node->next;
        }
    }

    while(p_node != NULL){
        push_back(list3, p_node->data);
        p_node = p_node->next;
    }
    while(q_node != NULL){
        push_back(list3, q_node->data);
        q_node = q_node->next;
    }

    return list3;
}

List_node *find_revise_node(List *list, int num)             //找到连表倒数第num个节点
{
    //若不知list->count,可以使用快慢指针来解决--->先让一个指针向后移动num-1步,
    //后 让另外一个指针和该指针一起向后移动,当该指针移动到末尾时即慢指针所在位
    //置即为所找节点
    #if 0
    List_node *p_node = NULL;
    int count = 0;

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

    p_node = list->head;
    count = list->count - num;
    while(count--){
        p_node = p_node->next;
    }

    return p_node;
    #endif

    #if 1

    List_node *p_node = NULL;
    List_node *q_node = NULL;
    int count = 0;

    if(list == NULL || num <= ZERO){
        return NULL;
    }

    p_node = list->head;
    q_node = list->head;
    count = num - 1;

    while(count--){
        p_node = p_node->next;
    }

    while(p_node->next != NULL){
        p_node = p_node->next;
        q_node = q_node->next;
    }

    return q_node;

    #endif
}

List_node *find_middle_node(List *list)                      //得到链表的中间节点
{
    List_node *mid_node = NULL;
    int count = 0;

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

    mid_node = list->head;

    count = list->count >> 1;

    while(count--){
        mid_node = mid_node->next;
    }

    return mid_node;
}

List *reverse_list(List *list)                               //逆置链表
{
    #if 0
    List *new_list = NULL;
    List_node *p_node = NULL;
   // List_node *q_node = NULL;

    if(list == NULL || list->count <= ONE){
        return new_list;
    }

    p_node = list->head;
    new_list = init_list();
    //q_node = new_list->head;

    while(p_node != NULL){
        push_front(new_list, p_node->data);
        p_node = p_node->next;
    }

    return new_list;
    #endif

    #if 1

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

    if(list == NULL || list->count <= ONE){
        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;
        r_node = q_node->next;
        p_node->next = NULL;
        do{
            q_node->next = p_node;    
            p_node = q_node;
            q_node = r_node;
            r_node = r_node->next;
        }while(r_node != NULL);
        q_node->next = p_node;
    }

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

List *copy_list(List *list)                                  //链表的拷贝
{
    List *result = NULL;
    List_node *p_node = NULL;

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

    result = init_list();
    p_node = list->head;

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

    return result;
}

Boolean is_list_intersect(List *list1, List *list2)          //判断两个链表是否有交点
{
    if(list1 == NULL || list2 == NULL || list1->count == ZERO
        || list2->count == ZERO){
        return FALSE;
    }

    return list1->tail == list2->tail;

#if 0
    if(list1->tail == list2->tail){
        return TRUE;
    }else{
        return FALSE;
    }
#endif
}

List_node *find_first_common_node(List *list1, List *list2)  //找到两个链表的第一个交点
{
    int len = 0;
    int l1_len = 0;
    int l2_len = 0;
    List_node *p_node = NULL;
    List_node *q_node = NULL;

    if(list1 == NULL || list2 == NULL || list1->count == ZERO 
        || list2->count == ZERO || is_list_intersect == FALSE){
        return NULL;
    }

    l1_len = list1->count;
    l2_len = list2->count;
    p_node = list1->head;
    q_node = list2->head;

    if(l1_len >= l2_len){
        len = l1_len - l2_len;
        while(len--){
            p_node = p_node->next;
        }
    }else{
        len = l2_len - l1_len;
        while(len--){
            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)            //删除链表的一个节点
{
    //用node的next的data覆盖node的data,并让node的next指向其next的next
    //然后将node的next删除
    List_node *p_node = NULL;

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

    p_node = list->head;

    if(node->next != NULL){
        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 *p_node = NULL;

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

    p_node = list->head;
    while(p_node != NULL){
        if(p_node == list->tail->next){
            return TRUE;
        }
        p_node = p_node->next;
    }   

    return FALSE;
}

Boolean has_circle2(List *list, List_node **intersect);
Boolean has_circle2(List *list, List_node **intersect)
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;

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

    p_node = q_node = list->head;

    while(q_node != NULL && q_node->next != NULL){
        p_node = p_node->next;
        q_node = q_node->next->next;

        if(p_node == q_node){

            return TRUE;
        }
    }

    return FALSE;
}

//如果函数有多个返回值,只有传入某个值指针类型,才可以将其传出
List_node *find_circle_begin(List *list)                     //找到链表环的入口
{
    List_node *p_node = NULL;

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

    p_node = list->head;

    do{
        if(p_node == list->tail->next){
            return p_node;
        }
        p_node = p_node->next;
    }while(p_node != NULL);

    return NULL;
}

List_node *find_circle_begin2(List *list);                     //找到链表环的入口
List_node *find_circle_begin2(List *list)                     //找到链表环的入口
{
    if(!has_circle2(list, &intersect)){
        return NULL;
    }
}

链表的测试代码如下:

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

#include "list.h"

int main(int ac, char **av)
{
    List *list = init_list();  //链表初始化
    List *list1 = init_list();
    List *list2 = init_list();
    List *list3 = NULL;
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    int i = 0;
    int result = 0;
    srand(time(NULL));

    for(i = 0; i < 10; ++i){
        push_front(list, rand() % 100);
    }

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

    printf("before sort show list:\n");
    print_list(list);
    printf("before sort show list1:\n");
    print_list(list1);
    sort_list_ascend(list);
    sort_list_ascend(list1);
    printf("after sort show list:\n");
    print_list(list);
    printf("after sort show list1:\n");
    print_list(list1);
    list2 = merge_two_lists(list, list1); 
    printf("after merge show list2:\n");
    print_list(list2);
    printf("after merge show list:\n");
    print_list(list);
    printf("after merge show list1:\n");
    print_list(list1);
    printf("after reverse show list2:\n");
    list3 = reverse_list(list2);
    printf("after reverse show list3:\n");
    print_list(list3);
    printf("倒数第num个节点\n");
    p_node = find_revise_node(list3, 5);
    printf("%d\n", p_node->data);
    //printf("中间节点\n");
    //printf("删除一个节点\n");
    //delete_one_node(list, );
    //print_list(list);

    printf("判断两个链表是否有交点\n");
    result = is_list_intersect(list, list1);
    printf("result is : %d\n", result);
    q_node = find_first_common_node(list, list1);
    printf("%d\n", p_node->data);

    sort_list_descend(list);
    print_list(list);

    destroy_list(&list);   //链表的销毁
    destroy_list(&list1);   //链表的销毁
    destroy_list(&list2);   //链表的销毁

    return 0;
}

测试结果如下:

[root@localhost list]# ./main 
before sort show list:
75 68 13 10 17 45 10 24 60 21 
before sort show list1:
43 8 32 88 52 8 51 87 36 20 
after sort show list:
10 10 13 17 21 24 45 60 68 75 
after sort show list1:
8 8 20 32 36 43 51 52 87 88 
after merge show list2:
8 8 10 10 13 17 20 21 24 32 36 43 45 51 52 60 68 75 87 88 
after merge show list:
10 10 13 17 21 24 45 60 68 75 
after merge show list1:
8 8 20 32 36 43 51 52 87 88 
after reverse show list2:
after reverse show list3:
88 87 75 68 60 52 51 45 43 36 32 24 21 20 17 13 10 10 8 8 
倒数第num个节点
13
判断两个链表是否有交点
result is : 0
13
75 68 60 45 24 21 17 13 10 10 
[root@localhost list]# 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值