• 指针应用-----链表二


    今天继续完善自己的链表,上次已经实现了链表的插入、遍历、销毁方法,对于链表的插入,我们上次是在头结点进行插入的,这次,我们来实现一个在任意结点进行插入的方法。

    实现链表的另外一种插入方法----在任意位置进行插入:

     在实现它之前,先实现获取任意位置的结点的函数,为便在实现任意插入时会使用到它,先在头文件中定义:

    list.h:

    #ifndef _LIST_H_
    #define _LIST_H_
    
    #include <assert.h>
    
    typedef struct node
    {
        int data;
        struct node* next;
    } node_t;
    
    typedef void (*FUNC)(node_t*);
    
    node_t* list_insert_front(node_t* head, int data);
    
    void list_for_each(node_t* head, FUNC f);
    
    node_t* list_free(node_t* head);
    
    node_t* list_get_node(node_t* head, int index);//获取指定位置的结点
    
    #endif /* _LIST_H_ */

    具体实现list.c:

    #include "list.h"
    #include <stdlib.h>
    
    node_t* list_insert_front(node_t* head, int data)
    {
        node_t* n = (node_t*)malloc(sizeof(node_t));
        assert(n != NULL);
        n->data = data;
        n->next = NULL;
    
        if (head == NULL)
            head = n;
        else
        {
            n->next = head;
            head = n;
        }
    
        return head;
    }
    
    void list_for_each(node_t* head, FUNC f)
    {
        while (head)
        {
            f(head);
            head = head->next;
        }
    }
    
    node_t* list_free(node_t* head)
    {
        node_t* tmp;
        while (head)
        {
            tmp = head;
            head = head->next;
            free(tmp);
        }
        return head;
    }
    
    node_t* list_get_node(node_t* head, int index)
    {
        assert(index >= 0);
    
        int j = 0;
        while (head && j < index)
        {
            head = head->next;
            j++;
        }
    
        if (j == index)//说明已经找到结点
            return head;
            
        return head;//说明最终head指向NULL,没有找到结点
    
    }

    上面的也可简写:

    node_t* list_get_node(node_t* head, int index)
    {
        assert(index >= 0);
    
        int j = 0;
        while (head && j < index)
        {
            head = head->next;
            j++;
        }
            
        return head;
    
    }

    测试一下:

    main.c:

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译运行:

    如果没有找到呢?

    main.c:

    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 5);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译运行:

    好了,接着正式来定义任意插入的函数:

    list.h:

    #ifndef _LIST_H_
    #define _LIST_H_
    
    #include <assert.h>
    
    typedef struct node
    {
        int data;
        struct node* next;
    } node_t;
    
    typedef void (*FUNC)(node_t*);
    
    node_t* list_insert_front(node_t* head, int data);
    
    void list_for_each(node_t* head, FUNC f);
    
    node_t* list_free(node_t* head);
    
    node_t* list_get_node(node_t* head, int index);
    
    node_t* list_insert_at(node_t* head, int data, int index);
    
    #endif /* _LIST_H_ */

    list.c:

    #include "list.h"
    #include <stdlib.h>
    
    node_t* list_insert_front(node_t* head, int data)
    {
        node_t* n = (node_t*)malloc(sizeof(node_t));
        assert(n != NULL);
        n->data = data;
        n->next = NULL;
    
        if (head == NULL)
            head = n;
        else
        {
            n->next = head;
            head = n;
        }
    
        return head;
    }
    
    void list_for_each(node_t* head, FUNC f)
    {
        while (head)
        {
            f(head);
            head = head->next;
        }
    }
    
    node_t* list_free(node_t* head)
    {
        node_t* tmp;
        while (head)
        {
            tmp = head;
            head = head->next;
            free(tmp);
        }
        return head;
    }
    
    node_t* list_get_node(node_t* head, int index)
    {
        assert(index >= 0);
    
        int j = 0;
        while (head && j < index)
        {
            head = head->next;
            j++;
        }
            
        return head;
    
    }
    
    node_t* list_insert_at(node_t* head, int data, int index)
    {
        assert(index >= 0);
    
        if (index == 0)//等于就是头插入结点,直接调用现成的方法
            return list_insert_front(head, data);
    
        node_t* p;
        p = list_get_node(head, index - 1);
        if (p == NULL)
        {
            fprintf(stderr, "error insert pos
    ");
            exit(EXIT_FAILURE);
        }
    
      //新建一个节点 node_t* n = (node_t*)malloc(sizeof(node_t)); assert(n != NULL); n->data = data; n->next = NULL;
      //将节点进行链接 n->next = p->next; p->next = n; return head; }

    说明:

    ①fprintf表示向什么地方输出,如fprintf(stdio,"hello!");等价于printf("hello!");

    ②exit()表示程序退出,参数EXIT_FAILURE代表错误退出,它还有另外一个宏定义EXIT_SUCCESS,代表成功退出

    程序测试:

    main.c:

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_insert_at(head, 15, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译:

    其中的fprintf需要头文件:

    所以在list.c中加入此头文件:

    再次编译,运行:

    如果插入失败会怎样呢?

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_insert_at(head, 15, 5);//这个位置没有元素,应该会插入失败
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译运行:

    实现链表的删除方法:

    先定义删除方法:

    list.h:

    #ifndef _LIST_H_
    #define _LIST_H_
    
    #include <assert.h>
    
    typedef struct node
    {
        int data;
        struct node* next;
    } node_t;
    
    typedef void (*FUNC)(node_t*);
    
    node_t* list_insert_front(node_t* head, int data);
    
    void list_for_each(node_t* head, FUNC f);
    
    node_t* list_free(node_t* head);
    
    node_t* list_get_node(node_t* head, int index);
    
    node_t* list_insert_at(node_t* head, int data, int index);
    
    node_t* list_remove_at(node_t* head, int index);
    
    #endif /* _LIST_H_ */

    具体实现,在实现前,先用一个简单的图来解释下:

    具体实现如下list.c:

    node_t* list_remove_at(node_t* head, int index)
    {
        assert(index >= 0);
        node_t* n;
        if (index == 0)//这是移除首结点
        {
            n = head;
            head = head->next;
            free(n);
        }
        else
        {
            node_t* p = list_get_node(head, index - 1);
            if (p == NULL || p->next == NULL)
            {
                fprintf(stderr, "error remove pos
    ");
                exit(EXIT_FAILURE);
            }
            n = p->next;
            p->next = n->next;
            free(n);
        }
    
        return head;
    }

    测试一下main.c:

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_insert_at(head, 15, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_remove_at(head, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译运行:

    如果移除的元素不存在呢?

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_insert_at(head, 15, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_remove_at(head, 5);//这个元素不存在,移除时会出错
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    运行:

    实现链表的查找方法:

    list.h:

    #ifndef _LIST_H_
    #define _LIST_H_
    
    #include <assert.h>
    
    typedef struct node
    {
        int data;
        struct node* next;
    } node_t;
    
    typedef void (*FUNC)(node_t*);
    
    node_t* list_insert_front(node_t* head, int data);
    
    void list_for_each(node_t* head, FUNC f);
    
    node_t* list_free(node_t* head);
    
    node_t* list_get_node(node_t* head, int index);
    
    node_t* list_insert_at(node_t* head, int data, int index);
    
    node_t* list_remove_at(node_t* head, int index);
    
    node_t* list_find(node_t* head, int data, int* ret);//ret代表找到的链表的索引位置,返回值代表找到的链表结点
    
    #endif /* _LIST_H_ */

    list.c:

    #include "list.h"
    #include <stdlib.h>
    #include <stdio.h>
    
    node_t* list_insert_front(node_t* head, int data)
    {
        node_t* n = (node_t*)malloc(sizeof(node_t));
        assert(n != NULL);
        n->data = data;
        n->next = NULL;
    
        if (head == NULL)
            head = n;
        else
        {
            n->next = head;
            head = n;
        }
    
        return head;
    }
    
    void list_for_each(node_t* head, FUNC f)
    {
        while (head)
        {
            f(head);
            head = head->next;
        }
    }
    
    node_t* list_free(node_t* head)
    {
        node_t* tmp;
        while (head)
        {
            tmp = head;
            head = head->next;
            free(tmp);
        }
        return head;
    }
    
    node_t* list_get_node(node_t* head, int index)
    {
        assert(index >= 0);
    
        int j = 0;
        while (head && j < index)
        {
            head = head->next;
            j++;
        }
            
        return head;
    
    }
    
    node_t* list_insert_at(node_t* head, int data, int index)
    {
        assert(index >= 0);
    
        if (index == 0)
            return list_insert_front(head, data);
    
        node_t* p;
        p = list_get_node(head, index - 1);
        if (p == NULL)
        {
            fprintf(stderr, "error insert pos
    ");
            exit(EXIT_FAILURE);
        }
    
        node_t* n = (node_t*)malloc(sizeof(node_t));
        assert(n != NULL);
        n->data = data;
        n->next = NULL;
    
        n->next = p->next;
        p->next = n;
    
        return head;
    }
    
    node_t* list_remove_at(node_t* head, int index)
    {
        assert(index >= 0);
        node_t* n;
        if (index == 0)
        {
            n = head;
            head = head->next;
            free(n);
        }
        else
        {
            node_t* p = list_get_node(head, index - 1);
            if (p == NULL || p->next == NULL)
            {
                fprintf(stderr, "error remove pos
    ");
                exit(EXIT_FAILURE);
            }
            n = p->next;
            p->next = n->next;
            free(n);
        }
    
        return head;
    }
    
    node_t* list_find(node_t* head, int data, int* ret)
    {
        *ret = -1;
        int i = 0;
        while (head)
        {
            if (head->data == data)
            {
                *ret = i;
                break;
            }
            head = head->next;
            i++;
        }
    
        return head;
    }

    测试main.c:

    #include "list.h"
    #include <stdio.h>
    
    void print_node(node_t* n)
    {
        printf("data=%d ", n->data);
    }
    
    int main(void)
    {
        node_t* head = NULL;
        head = list_insert_front(head, 30);
        head = list_insert_front(head, 20);
        head = list_insert_front(head, 10);
    
        list_for_each(head, print_node);
        putchar('
    ');
    
        node_t* n = NULL;
        n = list_get_node(head, 1);
        if (n != NULL)
            printf("data = %d
    ", n->data);
        else
            printf("not found
    ");
    
        head = list_insert_at(head, 15, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        head = list_remove_at(head, 1);
        list_for_each(head, print_node);
        putchar('
    ');
    
        int ret;
        n = list_find(head, 20, &ret);
        if (n != NULL)
            printf("data = %d index = %d
    ", n->data, ret);
        else
            printf("not found
    ");
    
        head = list_free(head);
        assert(head == NULL);
    
    
        return 0;
    }

    编译,运行:

    好了,今天的学习到这,关于链表,下次会再次进行完善,下次见。

  • 相关阅读:
    最富有客户的资产总量
    无重叠区间
    工作流分析推荐
    sharepoint外包和定制开发公司分析比较及推荐
    sharepoint开发企业信息门户系统分析及公司推荐
    北京sharepoint开发公司比较推荐
    国内市场主流专业的sharepoint开发公司分析比较及推荐
    北京工作流软件公司分析比较和推荐
    国内市场主流专业的工作流(bpm)软件分析、比较及推荐
    Hibernate的多对多实例
  • 原文地址:https://www.cnblogs.com/webor2006/p/3484812.html
Copyright © 2020-2023  润新知