美文网首页
[C指针]单链表:内存视角看待 getNode 以及 Delet

[C指针]单链表:内存视角看待 getNode 以及 Delet

作者: AkuRinbu | 来源:发表于2019-04-20 16:20 被阅读0次

学习笔记

[C指针]指针与结构体:完整源码 C语言 实现 单链表

https://www.jianshu.com/p/160a239086ae

本文结构

getNode源码
getNode内存示意图
deleteN源码
deleteN内存示意图

getNode 源码

Node * getNode(LinkedList * list, COMPARE compare, void * data) {
    Node * node = list->head;
    while(node != NULL) {
        if(compare(node->data, data) == 0) {
            return node;
        }
        node = node->next;
    }
    return NULL;

}

getNode 内存示意图

  • node = node->next; ,只是在不断改写node变量的值
node等于node的next的本质.png
  • compare(node->data, data) == 0

(参见学习笔记链接中的完整源码)
Node * getNode(LinkedList * list, COMPARE compare, void * data) {}
首先,是函数指针 typedef int (*COMPARE)(void *, void *);
接着,是结构体指针 Employee *sally = (Employee*) malloc(sizeof(Employee));
然后,是调用语句 Node * node = getNode(&linkedList, (COMPARE)compareEmployee, sally);
再看,compare(node->data, data) == 0 中的 node->data 以及 data 都是结构体指针
node->data 对应蓝色的那根箭头
data 对应红色那根箭头
(箭头实际都是不存在的,重点是都可以寻址到0x200)

image.png
  • 显示查找到的结点 displayEmployee((Employee *)node->data);

node->data 指向真正的结构体,但是它是void *,需要进行强制类型转换,在前面加上(Employee *)

displayEmployee((Employee *)node->data);

deleteN源码

void deleteN(LinkedList * list, Node * node) {
    if(node == list->head) {
        if(list->head == list->tail) {
            list->head = NULL;
            list->tail = NULL;
        } else {
            list->head = list->head->next;
        }   
    } else {        
        Node * tmp = list->head;
        while(tmp != NULL && tmp->next != node) {
            tmp = tmp->next;
        }
        if(tmp != NULL) {
            tmp->next = node->next; 
        }   
        if(tmp->next == NULL) {
            list->tail = tmp;
        }
    }
    free(node);

}

deleteN 算法结构

1、要删除的结点是头结点
1.1 头结点是唯一的结点
1.2 头结点不是唯一的结点
2、要删除的结点不是头结点

  • 边界分析:如果要删除的不是头结点,而是尾结点

tmp->next = node->next; 本质就是 tmp->next = NULL;
再加个 if(tmp->next == NULL) {} 设置新的尾结点指针;

下面专门写了一组删除尾结点的用例


边界分析:如果要删除的不是头结点,而是尾结点

deleteN内存示意图

  • deleteN 链表删除结点变化情况

void deleteN(LinkedList * list, Node * node){}node结点指针不是结构体指针

node 是结点指针
tmp->next = node->next; 写内存操作
free(node);是释放结点,不是释放结构体 删除 deleteN
  • 链表结点删除之后,结构体依旧存在

如果想要释放黄色部分结构体占用的内存,要写 free(sally)
sallyEmployee *sally = (Employee*) malloc(sizeof(Employee));

链表结点删除之后,结构体依旧存在

完整源码(用例是删除尾结点)

运行结果
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef void (*DISPLAY)(void *);
typedef int (*COMPARE)(void *, void *);

typedef struct _employee {
    char name[30];
    int age;
} Employee;

int compareEmployee(Employee * e1, Employee * e2){
    return strcmp(e1->name, e2->name);
}

void displayEmployee(Employee * employee){
    printf("%s,%d.\n", employee->name, employee->age);
}

typedef struct _node {
    void * data;
    struct _node * next;
}Node;

typedef struct _linkedList {
    Node * head;
    Node * tail;
} LinkedList;

void initializeList(LinkedList * list) {
    list->head = NULL;
    list->tail = NULL;
}

void addHead(LinkedList * list, void * data) {
    Node * node = (Node *) malloc(sizeof(Node));
    node->data = data;
    if(list-> head == NULL) {
        list->tail = node;
        node->next = NULL;
    } else {
        node->next = list->head;
    }
    list->head = node;
}


void addTail(LinkedList * list, void * data) {
    Node * node = (Node *) malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    if(list->head == NULL) {
        list->head = node;
    } else {
        list->tail->next = node;
    }
    list->tail = node;
}


void displayLinkedList(LinkedList * list, DISPLAY display) {
    Node * node = list->head;
    while(node != NULL) {
        if(node == list->head) printf("Head: ");
        if(node == list->tail) printf("Tail:");
        display(node->data);
        node = node->next;
    }
}


Node * getNode(LinkedList * list, COMPARE compare, void * data) {
    Node * node = list->head;
    while(node != NULL) {
        if(compare(node->data, data) == 0) {
            return node;
        }
        node = node->next;
    }
    return NULL;

}

void deleteN(LinkedList * list, Node * node) {
    if(node == list->head) {
        if(list->head == list->tail) {
            list->head = NULL;
            list->tail = NULL;
        } else {
            list->head = list->head->next;
        }   
    } else {        
        Node * tmp = list->head;
        while(tmp != NULL && tmp->next != node) {
            tmp = tmp->next;
        }
        if(tmp != NULL) {
            tmp->next = node->next; 
        }   
        if(tmp->next == NULL) {
            list->tail = tmp;
        }
    }
    free(node);

}


int main()
{
    LinkedList linkedList;
    
    Employee *samuel = (Employee*) malloc(sizeof(Employee));
    strcpy(samuel->name, "Samuel");
    samuel->age = 32;
    
    Employee *sally = (Employee*) malloc(sizeof(Employee));
    strcpy(sally->name, "sally");
    sally->age = 28;
    
    Employee *susan = (Employee*) malloc(sizeof(Employee));
    strcpy(susan->name, "susan");
    susan->age = 45;
    
    initializeList(&linkedList);
    
    addHead(&linkedList, samuel);
    addHead(&linkedList, sally);
    addHead(&linkedList, susan);
    
    displayLinkedList(&linkedList, (DISPLAY)displayEmployee);
    
    Node * node = getNode(&linkedList, (COMPARE)compareEmployee, samuel);
    displayEmployee((Employee *)node->data);
    
    printf("--Message:Delete samuel:\n");
    deleteN(&linkedList, node);
    displayLinkedList(&linkedList, (DISPLAY)displayEmployee);
    
    
    printf("--Message:addTail(sara):\n");
    Employee *sara = (Employee*) malloc(sizeof(Employee));
    strcpy(sara->name, "sara");
    sara->age = 22;
    addTail(&linkedList, sara);
    displayLinkedList(&linkedList, (DISPLAY)displayEmployee);

    return 0;
}

相关文章

  • [C指针]单链表:内存视角看待 getNode 以及 Delet

    学习笔记 [C指针]指针与结构体:完整源码 C语言 实现 单链表https://www.jianshu.com/p...

  • [C指针]单链表:内存视角看待 addHead 函数的本质(内存

    学习笔记 [C指针]指针与结构体:完整源码 C语言 实现 单链表https://www.jianshu.com/p...

  • 链表

    链表:通过“指针”将零散的内存块联系起来。常见链表结构:单链表、循环链表和双链表。 单链表 对比数组学习单链表 循...

  • 2018-12-01

    数据结构使用二级指针创建单链表以及单链表的各种操作 //单链表创建 #include #include #incl...

  • 《数据结构与算法之美》04——链表

    链表:通过“指针”将一组零散的内存块串联起来使用。 数组vs链表 三种常见的链表:单链表、双向链表、循环链表。 单...

  • 0876-链表的中间结点

    链表的中间结点 方案一 使用快慢指针 借助单链表实现 C-源代码

  • 2018-09-13

    用c语言创建单链表,参数采用二级指针。 源码如下: //单链表头插法创建 #include #include #d...

  • 链表

    链表:非连续内存空间,链表中每个元素还有next指针指向下一个元素 单端链表:只有next指针指向下一个 双端链表...

  • 链表

    链表通过指针将一组零散的内存空间串联起来使用。单链表 双向链表 循环链表 链表的特点 每一个内存块称之为节点为了将...

  • 数据结构之链表笔记

    前言 其实链表的心法就是“指针的操作” 单链表 单链表的结点包括:data(数据)、next指针next指针就是指...

网友评论

      本文标题:[C指针]单链表:内存视角看待 getNode 以及 Delet

      本文链接:https://www.haomeiwen.com/subject/jnxlgqtx.html