算法精解(C语言描述) 第5章 读书笔记
第5章
5.1 单链表
/* -------------------------------- list.h -------------------------------- */
#ifndef LIST_H
#define LIST_H #include <stdlib.h> /* Define a structure for linked list elements.*/
typedef struct ListElmt_
{
void *data;
struct ListElmt_ *next;
} ListElmt; /* Define a structure for linked lists.*/
typedef struct List_
{
int size;
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
ListElmt *head;
ListElmt *tail;
} List; /* --------------------------- Public Interface --------------------------- */
void list_init(List *list, void (*destroy)(void *data));//whl-?其destroy参数的用法?
void list_destroy(List *list);
int list_ins_next(List *list, ListElmt *element, const void *data);
int list_rem_next(List *list, ListElmt *element, void **data); #define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)
#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next) #endif
/* -------------------------------- list.c -------------------------------- */
#include <stdlib.h>
#include <string.h>
#include "list.h"
/* ------------------------------- list_init ------------------------------ */
void list_init(List *list, void (*destroy)(void *data))//若链表包含不该释放的数据,则destroy应设置为NULL
{
/* Initialize the list. */
list->size = ;
list->destroy = destroy;//把函数指针成员destroy设置为定义的析构函数
list->head = NULL;
list->tail = NULL;
return;
}
/* ----------------------------- list_destroy ----------------------------- */
void list_destroy(List *list)//若传给list_init的参数destroy不为NULL,则移除链表中每个元素时都调用该函数一次
{
void *data;
/* Remove each element. */
while (list_size(list) > )
{
if (list_rem_next(list, NULL, (void **)&data) == && list->destroy != NULL)
{
/* Call a user-defined function to free dynamically allocated data. */
list->destroy(data);
}
}
/* No operations are allowed now, but clear the structure as a precaution. */
memset(list, , sizeof(List));
return;
}
/* ----------------------------- list_ins_next ---------------------------- */
int list_ins_next(List *list, ListElmt *element, const void *data) //在list指定的链表中element后面插入一个新元素
{
ListElmt *new_element;
/* Allocate storage for the element. */
if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
{
return -;
}
/* Insert the element into the list. */
//new_element->data = (void *)data;
new_element->data = (void *)data;
if (element == NULL) //若element设置为NULL,则新元素插入链表头部
{
/* Handle insertion at the head of the list. */
if (list_size(list) == )
list->tail = new_element;
new_element->next = list->head;
list->head = new_element;
}
else
{
/* Handle insertion somewhere other than at the head. */
if (element->next == NULL)
list->tail = new_element;
new_element->next = element->next;
element->next = new_element;
}
/* Adjust the size of the list to account for the inserted element. */
list->size++;
return ;
}
/* ----------------------------- list_rem_next ---------------------------- */
int list_rem_next(List *list, ListElmt *element, void **data)//移除由list指定的链表中element后的那个元素
{
ListElmt *old_element; /* Do not allow removal from an empty list. */
if (list_size(list) == )
return -; /* Remove the element from the list. */
if (element == NULL)//若element设置为NULL,则移除链表头部元素
{
/* Handle removal from the head of the list. */
*data = list->head->data;
old_element = list->head;
list->head = list->head->next;
if (list_size(list) == )
list->tail = NULL;
}
else {
/* Handle removal from somewhere other than the head. */
if (element->next == NULL)
return -;
*data = element->next->data;
old_element = element->next;
element->next = element->next->next;
if (element->next == NULL)
list->tail = element;
}
/* Free the storage allocated by the abstract data type. */
free(old_element);
/* Adjust the size of the list to account for the removed element. */
list->size--;
return ;
}
算法精解(C语言描述) 第5章 读书笔记的更多相关文章
- 机器学习|线性回归算法详解 (Python 语言描述)
原文地址 ? 传送门 线性回归 线性回归是一种较为简单,但十分重要的机器学习方法.掌握线性的原理及求解方法,是深入了解线性回归的基本要求.除此之外,线性回归也是监督学习回归部分的基石. 线性回归介绍 ...
- GC算法精解(五分钟让你彻底明白标记/清除算法)
GC算法精解(五分钟让你彻底明白标记/清除算法) 相信不少猿友看到标题就认为LZ是标题党了,不过既然您已经被LZ忽悠进来了,那就好好的享受一顿算法大餐吧.不过LZ丑话说前面哦,这篇文章应该能让各位彻底 ...
- GC算法精解(五分钟教你终极算法---分代搜集算法)
GC算法精解(五分钟教你终极算法---分代搜集算法) 引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们 ...
- [转帖]算法精解:DAG有向无环图
算法精解:DAG有向无环图 https://www.cnblogs.com/Evsward/p/dag.html DAG是公认的下一代区块链的标志.本文从算法基础去研究分析DAG算法,以及它是如何运用 ...
- 数据结构与算法分析——C语言描述 第三章的单链表
数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...
- 【2018.08.13 C与C++基础】C++语言的设计与演化读书笔记
先占坑 老实说看这本书的时候,有很多地方都很迷糊,但却说不清楚问题到底在哪里,只能和Effective C++联系起来,更深层次的东西就想不到了. 链接: https://blog.csdn.net/ ...
- 算法精解(C语言描述) 第4章 读书笔记
第4章 算法分析 1.最坏情况分析 评判算法性能的三种情况:最佳情况.平均情况.最坏情况. 为何要做最坏情况分析: 2.O表示法 需关注当算法处理的数据量变得无穷大时,算法性能将趋近一个什么样的值.一 ...
- 算法精解(C语言描述) 第3章 读书笔记
第3章 递归 1.基本递归 假设想计算整数n的阶乘,比如4!=4×3×2×1. 迭代法:循环遍历其中的每一个数,然后与它之前的数相乘作为结果再参与下一次计算.可正式定义为:n! = (n)(n-1)( ...
- JVM内存管理------GC算法精解(复制算法与标记/整理算法)
本次LZ和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一章在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算 ...
随机推荐
- javascript函数值的重写
原文:javascript函数值的重写 javascript函数值的重写 定义了一个函数,需要重写这个函数并使用原先的函数值.做法是: 1.定义一个变量让原先函数的值指向它,把原先函数的指向一个新的函 ...
- C++ 文件的复制、删除、重命名
一.文件的复制 #include <iostream>#include <fstream>using namespace std; int CopyFile(char *Sou ...
- 普林斯顿大学算法课 Algorithm Part I Week 3 重复元素排序 - 三路快排 Duplicate Keys
很多时候排序是为了对数据进行归类,这种排序重复值特别多 通过年龄统计人口 删除邮件列表里的重复邮件 通过大学对求职者进行排序 若使用普通的快排对重复数据进行排序,会造成N^2复杂度,但是归并排序和三路 ...
- 【Python】iiacm_filemaker ——简易的.cpp文件创建即初始化脚本,ACMer专用
代码已全部重写,上次写的真是不忍直视…… 今天刚刚接触Python,本着学以致用的原则,就写了一个按照要求自动生成.cpp文件并初始化头文件的脚本. 确定你的linux中安装了Python,将下面的代 ...
- ios模拟器安装.app
相对于xcode的run,然后再在安装到模拟器上测试,如果是个人开发的话,那还好. 要是是团队开发,那每次其他的童鞋就都需要update最新的文件下来再编译运行了. 而且,一些测试的童鞋也不会打开xc ...
- android入门——Service
简单记录一下四大组件之一的Service的简单实用. 先是最简单的用法,服务的开关,onBind方法的使用 package com.example.wkp.service; import androi ...
- asp.net预览图片
Aspx code <table> <tr> <td class="style3"> <asp:Label ID="Label1 ...
- ora-06502
执行一个存储过程时报这个错误 ORA-06502: PL/SQL: 数字或值错误 发现是定义的字符串的缓冲区太小,赋给字符串的值又太大 修改varchar2(20) → varchar2(200 ...
- C# - 重定义一个接口的实现
using System;using System.Collections.Generic;using System.Text; namespace MyTester{ public inter ...
- java打包/命令行方式运行jar(命令行进行程序测试)
public class Testtmp { public static void main(String[] args) { // TODO Auto-generated method stub f ...