C语言链表的基本操作:增、删、遍历、翻转

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1075355798/article/details/80000925

内容

实现了单链表的基本操作,包括:节点的创建、添加、插入、删除、遍历、翻转。

代码

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

typedef unsigned long Data;

typedef struct node{
    Data data;
    struct node *next;
}link_node,*pnode;

static pnode free_list(pnode head)
{
    pnode temp = NULL;
    if (!head)
        return head;
    //printf("into %s\n",__func__);
    temp = head;

    printf("free data :\n");
    while (temp != NULL) {
        temp = temp->next;
        printf("%lu ", head->data);
        free(head);
        head = temp;
    }
    printf("\n");
    //printf("leave %s\n",__func__);
    return head;
}

static void print_list(pnode head)
{
    pnode temp  = NULL;
    //printf("into %s\n",__func__);
    if (!head) {
        printf("List is null!\n");
        return ;
    }

    temp = head;

    printf("print data :\n");
    while (temp != NULL) {
        printf("%lu ", temp->data);
        temp = temp->next;
    }

    printf("\n");
    //printf("leave %s\n",__func__);
}

static pnode reverse_list(pnode head)
{
    if (!head || head->next == NULL) {
        return head;
    }

    pnode temp = head, pre = head->next;

    temp->next = NULL;

    //while(pre->next != NULL)  //err
    while (pre != NULL) {
        head = pre;
        pre = pre->next;
        head->next = temp;
        temp = head;
    }
    temp = NULL;
    return head;
}

static pnode dele_first_node(pnode head)
{
    if (head == NULL) {
        return head;
    }

    pnode temp = head;
    if (temp->next != NULL)
        temp = temp->next;

    Data data = head->data;
    free(head);
    head = temp;
    printf("delet the first node, the data=%lu\n", data);

    return head;
}

static pnode insert_node_first(pnode head, pnode node)
{
    assert(node);

    printf("insert the data=%lu\n", node->data);
    pnode temp = head;
    head = node;
    node->next = temp;

    return head;
}

static pnode add_node_tail(pnode head, pnode node)
{
    //printf("into %s\n",__func__);
    assert(node);

    if (head == NULL) {
        head = node;
        return head;
    }

    pnode temp = head;
    //printf("%s, list data : ", __func__);
    while (temp->next != NULL) {
        temp = temp->next;
    }
    temp->next = node;
    //printf("leave %s\n",__func__);
    return head;
}

static pnode creat_node(Data data)
{
    pnode node = (pnode)malloc(sizeof(link_node));
    if (!node) {
        perror("malloc:");
        return NULL;
    }
    //printf("into %s\n",__func__);
    memset(node, 0, sizeof(link_node));
    node->data = data;
    node->next = NULL;
    //printf("leave %s\n",__func__);
    return node;
}

int main(void)
{
    pnode head = NULL;
    pnode new_node = NULL;
    //srand((unsigned)time(NULL));  
    for(int i = 0; i < 10; i++) {  
        //new_node = creat_node(rand());
        new_node = creat_node(i*100);
        head = add_node_tail(head, new_node);
    } 
    print_list(head);
    head = dele_first_node(head);
    print_list(head);
    new_node = creat_node(1234);
    head = insert_node_first(head, new_node);
    print_list(head);
    head = reverse_list(head);
    print_list(head);
    if(free_list(head)) {
        printf("unlikely: maybe some exception !!!!!\n");
    }
    return 0;   
}

测试结果

./a.out
print data :
0 100 200 300 400 500 600 700 800 900
delet the first node, the data=0
print data :
100 200 300 400 500 600 700 800 900
insert the data=1234
print data :
1234 100 200 300 400 500 600 700 800 900
print data :
900 800 700 600 500 400 300 200 100 1234
free data :
900 800 700 600 500 400 300 200 100 1234

总结

链表很简单,总结点如下:
1. 注意 malloc 的使用,注意 free 的使用;
2. 区分何时判断节点为空,何时判断节点的下一个节点为空,代码表示为, if(node == NULL) 和 if (node->next == NULL);
3. 链表的翻转,链表的打环,链表环点检测,链表的中间点检测,都是在指针的基础上做文章。单链表的翻转,需要一个前指针,一个后指针,一个临时节点指针,它们前进的“速度”是一样的;而后面几个问题的解决,需要“快慢”指针进行处理,所谓的快慢,一个是 temp = tem->next; 一个是 temp = temp->next->next,而在这过程中,一定处理好总结的第二点。
4. 链表和数据的关系,本文的测试代码,链表节点中的数据类型是统一的,就形成了一种链表节点包含数据的关系。但是在实际中,如果希望同一条链表上,可以挂载不同类型的数据,那么本文的示例代码就不再合适,就必须想办法,让数据来包含链表,最直接的做法,就是在数据结构体中,包含一个链表的成员,这一部分,可参考 Linux kernel 的链表实现方法。

猜你喜欢

转载自blog.csdn.net/q1075355798/article/details/80000925