目录

1.与顺序表的对比

2.链表

2.2链表的概念和结构

3.2 链表的分类

3.3接口以及实现

LinkList.h

LinkList.c

3.3.1链表的打印

3.3.2获取一个新节点

3.3.3获取的链表长度

3.3.4单链表查找

3.3.4销毁链表

3.3.5链表删除

尾删

头删

pos位置之后的值

3.3.6链表增加

尾插

头插

pos之后插入

pos之前插入


1.与顺序表的对比

书接上回!我们修炼了顺序表的内功,但是在很多使用场景,他都很受限制!

缺点:

  1. 插入删除的时候,还记得吗!我们都要搬运元素到指定位置,时间复杂度是O(N).
  2. 你的顺序表容量是提前给的,扩容的时候还要拷贝数据,开辟新空间,释放旧空间,会有很大的性能消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。若每次扩容扩少一点,则会导致频繁扩容,频繁扩容同样也会有性能消耗。

优点:

  1. 存储空间是一段连续的内存空间,我们可以通过下标随机访问

优劣结合,这本功法会有很大的内耗!顺序表不能按需申请和释放空间,他是连续的内存空间!他的删除也是会在搬运元素,无法做到存一个数据申请一块空间,删除一个数据释放一块空间。

2.链表

我向师傅询问这顺序表的内耗是用何许方法解决的?师傅敲敲我的头指向了另外的一本功法《C语言程序设计》 是指针! 我要加指针!

2.2链表的概念和结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

链表的结构很像大手拉小手,我的大手就相当于上一个节点指针域,小手就是下一个节点的地址。
图解

代码解释 

void Text() {Node* LinkList = NULL;Node* Node1 = malloc(sizeof(Node));Node* Node2 = malloc(sizeof(Node));Node* Node3 = malloc(sizeof(Node));Node1->data = 1;Node2->data = 2;Node3->data = 3;Node1->next = Node2;Node2->next = Node3;Node3->next = NULL;LinkList = Node1;return 0;
}

这个时候链表第一个节点的指针域还没有指向下一个节点

就把值赋过去了,大手拉小手!从上图可以看出链表在物理上不是连续的,在逻辑上是连续的。

节点都是malloc从堆上申请出来的。

3.2 链表的分类

1. 单向或者双向

2. 带头或者不带头

 3. 循环或者非循环

3.3接口以及实现

直接上代码

LinkList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int Datatype;typedef struct LinkList {struct LinkList* next;Datatype data;
}Node;//打印链表
void PrintLinkList(Node* plist);//获取一个新节点
Node* LinkListCreat(Datatype data);//单链表尾插
void LinkListPushBack(Node** pplist, Datatype data);//单链表的尾删
void LinkListPopBack(Node** pplist);//单链表的头插
void LinkListPushFront(Node** pplist, Datatype data);//单链表头删
void LinkListPopFront(Node** pplist);//单链表查找
Node* LinkListFind(Node* plist, Datatype data);//单链表在pos位置之前插入x
void LinkListInsertBefore(Node** pplist, Node* pos, Datatype data);//单链表在pos位置之后插入x
void LinkListInsertAfter(Node* pos, Datatype data);//单链表删除pos位置之后的值
void LinkListEraseAfter(Node* pos);//获取的链表长度
int LinkListSize(Node* plist);//销毁链表
void LinkListDestroy(Node** pplist);

LinkList.c

#include "LinkList.h"
//打印链表
void PrintLinkList(Node* plist)
{Node* cur = plist;//遍历链表输出while (cur){printf("%d-->", cur->data);cur = cur->next;}printf("NULL\n");
}
//获取一个新节点
Node* LinkListCreat(Datatype data)
{//开辟空间获取一个节点的大小Node* Newnode = (Node*)malloc(sizeof(Node));//malloc之后要判空是否申请成功if (Newnode == NULL){assert(0);return NULL;}//新节点的下一个还没链接那就置空Newnode->next = NULL;Newnode->data = data;return Newnode;
}// 单链表尾插
void LinkListPushBack(Node** pplist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//我们的遍历指针既然是要尾插那我们就要先找到最后那个Node* cur = *pplist;//用刚刚写的那个创建节点的方法取到新节点的地址Node* NewNode= LinkListCreat(data);//一个节点都没有//这个NewNode给到操作链表的指针if (NULL == *pplist) {*pplist = NewNode;return;}//里面就有节点我们直接找到最后一个节点//把新节点的地址交给最后一个节点的nextelse{while (cur->next) {cur = cur->next;}cur->next = NewNode;}}// 单链表的尾删
void LinkListPopBack(Node** pplist)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//遍历指针Node* cur = *pplist;//这个用来存上一个节点地址Node* prev = NULL;//空链表情况if (NULL == *pplist){printf("你的链表为空!");return;}//链表只有有个节点的情况else if (NULL == *(pplist)->next){free(*pplist);*pplist = NULL;}//开始遍历找到尾节点else{while (cur) {//把这个节点先存储下来prev = cur;cur = cur->next;}free(cur);//让他下一个节点为空prev->next = NULL;}
}
// 单链表的头插
void LinkListPushFront(Node** pplist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//创建一个新的节点准备插入Node* NewNode = LinkListCreat(data);//链表为空直接插入if (*pplist == NULL){*pplist = NewNode;return;}//新节点的next链接原来链表的头//原来指向链表头的指针指向新节点else {NewNode->next = *pplist;*pplist = NewNode;}//还可以这样写//assert(pplist);//Node* NewNode = LinkListCreat(data);//NewNode->next = *pplist;//*pplist = NewNode;
}
// 单链表头删
void LinkListPopFront(Node** pplist)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//设置一个指针指向要删除的节点Node* DelNode = NULL;if (NULL == *pplist){return;}//删的是第一个节点那就指向表头DelNode = *pplist;//表头指针指向被删除的下一个节点*pplist = DelNode->next;free(DelNode);
}
// 单链表查找
Node* LinkListFind(Node* plist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(plist);//找到对应节点 赋给FindNode* FindNoed = plist;Node* cur = plist;//空链表就直接返回了if (NULL == plist){printf("你的链表为空!");return;}//循环查找while (cur){if (cur->data == data);{//找到了返回FindNoed = cur;return FindNoed;}cur = cur->next;}}
//任意位置之前插入
void LinkListInsertBefore(Node** pplist, Node* pos, Datatype data)
{assert(pplist);//找到要插入的位置Node* Prior = *pplist;Node* NewNode = NULL;//链表为空我就调用我尾插这个方法就好了if (pos == *pplist) {LinkListPushFront(pos, data);}else if (NULL == pos){return;}else {NewNode = LinkListCreat(data);while (Prior->next != pos){Prior = Prior->next;}Prior->next = NewNode;NewNode->next = pos;}
}
//单链表在pos位置之后插入x
//为啥只能是在后面插入呢因为这是链表不是顺序表那种连续的
//不能访问上一个节点 循环链表和双向链表可以解决
//亦或是再加一个指针找到前一个
void LinkListInsertAfter(Node* pos, Datatype data)
{Node* NewNode = NULL;if (NULL == pos){return;}// 将新节点插入到pos之后NewNode = LinkListCreat(data);NewNode->next = pos->next;pos->next = NewNode;
}// 单链表删除pos位置之后的值
void LinkListEraseAfter(Node* pos)
{Node* DelNode = NULL;//校验pos的合法性if (NULL == pos || NULL == pos->next){return;}//找到删的节点DelNode = pos->next;//pos位置跟删除的下一个结点连起来pos->next = DelNode->next;free(DelNode);
}int LinkListSize(Node* plist)
{assert(plist);//遍历链表就完事了Node* cur = plist;//给个遍历指针 指向链表第一个节点//因为不改变链表的值,我们传入int count = 0;while (cur) {//count ++ 计数器count++;cur = cur->next;}return count;
}void LinkListDestroy(Node** pplist)
{//断言链表是否存在assert(pplist);//两个指针一个标记删除节点一个遍历Node* DelNode = *pplist;while (DelNode) {//遍历这个指针先指向下一个节点//要不以后释放之后下一个节点的地址就不见了*pplist = DelNode->next;//释放这个要删除的节点free(DelNode);//这个删掉了该下一个了//标记要删除的节点用遍历指针给到刚刚保存了下一个节点地址DelNode = *pplist;}
}
int main()
{}

3.3.1链表的打印

void PrintLinkList(Node* plist)
{Node* cur = plist;//遍历链表输出while (cur){printf("%d-->", cur->data);cur = cur->next;}printf("NULL\n");
}

定义一个遍历指针把链表遍历一遍,每次把对应的结点通过遍历指针访问节点数据域来取出 ,为啥先说打印呢,因为打印可以让我们更好的理解遍历链表!

那怎么循环起来遍历的呢,还是那就话大手拉小手,怎么拉?我的这个节点的指针域放的是下一个一个节点的地址!

那思路我们有了怎么用代码实现?我们可以吧循环展开

cur = cur->next;

这句其实就是cur ->next->next->next.....我们顺着第一个节点就把全部的节点就找到了!但是有个缺陷就是我现在指针已经在N个节点这块了那我能不能对指针--看第N个节点?不可以!对指针进行加加减减是对指针指向的目标的大小进行加加减减,是我们是加加减减了一个节点的大小!那也不能访问到,物理上不连续!

3.3.2获取一个新节点

//获取一个新节点
Node* LinkListCreat(Datatype data)
{//开辟空间获取一个节点的大小Node* Newnode = (Node*)malloc(sizeof(Node));//malloc之后要判空是否申请成功if (Newnode == NULL){assert(0);return NULL;}//新节点的下一个还没链接那就置空Newnode->next = NULL;Newnode->data = data;return Newnode;
}

直接malloc个一个Node大小的节点,malloc是否申请成功要判断一下,然后返回这个新节点的地址。

3.3.3获取的链表长度

//获取的链表长度
int LinkListSize(Node* plist)
{assert(plist);//遍历链表就完事了Node* cur = plist;//给个遍历指针 指向链表第一个节点//因为不改变链表的值,我们传入int count = 0;while (cur) {//count ++ 计数器count++;cur = cur->next;}return count;
}

给个遍历指针,来个计数器还有比这个更简单的了吗?

3.3.4单链表查找

// 单链表查找
Node* LinkListFind(Node* plist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(plist);//找到对应节点 赋给FindNode* FindNoed = plist;Node* cur = plist;//空链表就直接返回了if (NULL == plist){printf("你的链表为空!");return;}//循环查找while (cur){if (cur->data == data);{//找到了返回FindNoed = cur;return FindNoed;}cur = cur->next;}}

老规矩进来先看看这个货是不是空的要是空那就是说链表不存在!plist这个指针指的是链表第一个节点的地址,他都是空就说明你的链表就不存在!那就不找了。纯在就更简单了if判断找得到了返回地址。

3.3.4销毁链表

void LinkListDestroy(Node** pplist)
{//断言链表是否存在assert(pplist);//两个指针一个标记删除节点一个遍历Node* DelNode = *pplist;while (DelNode) {//遍历这个指针先指向下一个节点//要不以后释放之后下一个节点的地址就不见了*pplist = DelNode->next;//释放这个要删除的节点free(DelNode);//这个删掉了该下一个了//标记要删除的节点用遍历指针给到刚刚保存了下一个节点地址DelNode = *pplist;}
}

为啥要用这个二级指针传参呢?一级指针不行吗?

我们翻开c的秘籍在复习一下吧!

void swap(int a,int b) {int temp = a;a = b;b = temp;}
int main()
{int a = 2;int b = 3;swap(a, b);printf("a = %d\n", a);printf("b = %d\n", b);
}

a和b的值能交换吗?是不能的!形参是实参的一份临时拷贝,在函数调用时会发生这个临时拷贝,函数调用结束这个临时拷贝就会释放,你的交换其实只是在函数内部进行交换了,并没有把实际的结果传回来,形参和实参分别占有不同内存块,对形参的修改不会影响实参。那我怎么办?传址传参就可以,在c++中还可以用引用(引用是指针常量)

void swap(int* a,int* b) {int temp = *a;*a = *b;*b = temp;}
int main()
{int a = 2;int b = 3;swap(&a,&b);printf("a = %d\n", a);printf("b = %d\n", b);
}

传址调用是把函数外部创建变量的内存地址,传递给函数参数,直接通过地址修改这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
就是实际参数传到函数里了,可以通过形式参数修改实际参数。

回到我们的plist那他不是也是指针吗?他说你节点的地址,你这个函数调用后这个是不是也释放了,我们是要通过这个plist操控链表呀,想让他不被改变,那就应该存plist的地址,也就是指针变量的地址,也就是二级指针变量。

void LinkListDestroy(Node** pplist)
{//断言链表是否存在assert(pplist);//两个指针一个标记删除节点一个遍历Node* DelNode = *pplist;while (DelNode) {//遍历这个指针先指向下一个节点//要不以后释放之后下一个节点的地址就不见了*pplist = DelNode->next;//释放这个要删除的节点free(DelNode);//这个删掉了该下一个了//标记要删除的节点用遍历指针给到刚刚保存了下一个节点地址DelNode = *pplist;}
}

这个断言是必须要有的,你pplist都是空说明你链表就是有问题,都没有创建!给一个删除指针专门指向删除的那个节点,先移动我们的标记指针pplist让他指向下一个去,在释放前一个,在吧这个删除指针指向下一个节点地址,那有人会说了我要这个删除指针干嘛呀?我直接free(*pplist)不就完事了,你free掉了你的大手拉小手的链接也断了因为当前节点存的下一个节点的地址!你free就没啦!

3.3.5链表删除

尾删

// 单链表的尾删
void LinkListPopBack(Node** pplist)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//遍历指针Node* cur = *pplist;//这个用来存上一个节点地址Node* prev = NULL;//空链表情况if (NULL == *pplist){printf("你的链表为空!");return;}//链表只有有个节点的情况else if (NULL == *(pplist)->next){free(*pplist);*pplist = NULL;}//开始遍历找到尾节点else{while (cur) {//把这个节点先存储下来prev = cur;cur = cur->next;}free(cur);//让他下一个节点为空prev->next = NULL;}
}

尾删你就要考虑许多情况,首先链表是空的,解引用pplist是否为空,空就直接返回不操作了,空荡荡删啥呢?然后就是只有个节点咱就看这个节点的下一个是不是空的也就是解引用pplist看看你的next是撒捏?嚯好家伙空!这不简单直接释放,变空链表解引用pplist给我指向空去,接下来就是展现操作的时候,先遍历找到最后一个,用个prve把上个节点保存一下让他的next指向空!然后我们释放最后一个就好了。

这样好麻烦呀!还要分情况那有没有别的方法。

 assert(pplist);Node* cur = *pplist;while (cur->next->next != NULL){cur = cur->next;}free(cur->next);cur->next = NULL;

assert处理了空还有没有节点的情况,然后我也不需要刚刚那个prev了只是要要next的next就好了,最后把最后一个一删除就完事了。

头删

// 单链表头删
void LinkListPopFront(Node** pplist)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//设置一个指针指向要删除的节点Node* DelNode = NULL;if (NULL == *pplist){return;}//删的是第一个节点那就指向表头DelNode = *pplist;//表头指针指向被删除的下一个节点*pplist = DelNode->next;free(DelNode);
}

标记一个删除指针指向你要删除的节点,看看链表是不是空的,不是就开始删,删除指针指向表头,让我们的链表操作指针指向下一个去,free掉这个DelNode,为啥要这个删除指针呢?保存下一个节点的地址呀,要不然你直接释放了,你的表头指针就寄了,你大手拉不上小手了。

pos位置之后的值

// 单链表删除pos位置之后的值
void LinkListEraseAfter(Node* pos)
{Node* DelNode = NULL;//校验pos的合法性if (NULL == pos || NULL == pos->next){return;}//找到删的节点DelNode = pos->next;//pos位置跟删除的下一个结点连起来pos->next = DelNode->next;free(DelNode);
}

校验pos的合法性,找到删的节点,pos位置跟删除的下一个结点连起来,这个删除节点也是一个储存下一个节点的地址信息的。

pos->next = DelNode->next;
//其实就是
pos->next=pos->next->next;

3.3.6链表增加

尾插

// 单链表尾插
void LinkListPushBack(Node** pplist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//我们的遍历指针既然是要尾插那我们就要先找到最后那个Node* cur = *pplist;//用刚刚写的那个创建节点的方法取到新节点的地址Node* NewNode= LinkListCreat(data);//一个节点都没有//这个NewNode给到操作链表的指针if (NULL == *pplist) {*pplist = NewNode;return;}//里面就有节点我们直接找到最后一个节点//把新节点的地址交给最后一个节点的nextelse{while (cur->next) {cur = cur->next;}cur->next = NewNode;}}

还是先assret老规矩进来先看看这个货是不是空的要是空那就是说链表不存在!我们的遍历指针既然是要尾插那我们就要先找到最后那个,用刚刚写的那个创建节点的方法取到新节点的地址,然后开始分情况,一个节点都没有,这个NewNode给到操作链表的指针,里面就有节点我们直接找到最后一个节点,把新节点的地址交给最后一个节点的next。

头插

// 单链表的头插
void LinkListPushFront(Node** pplist, Datatype data)
{//老规矩进来先看看这个货是不是空的//要是空那就是说链表不存在!assert(pplist);//创建一个新的节点准备插入Node* NewNode = LinkListCreat(data);//链表为空直接插入if (*pplist == NULL){*pplist = NewNode;return;}//新节点的next链接原来链表的头//原来指向链表头的指针指向新节点else {NewNode->next = *pplist;*pplist = NewNode;}//还可以这样写//assert(pplist);//Node* NewNode = LinkListCreat(data);//NewNode->next = *pplist;//*pplist = NewNode;
}

开辟一个新的节点把他的地址给到NewNode,要是我们的链表为空直接把解引用pplist指向新节点的地址,新节点的next链接原来链表的头,原来指向链表头的指针指向新节点。

pos之后插入

//单链表在pos位置之后插入x
//为啥只能是在后面插入呢因为这是链表不是顺序表那种连续的
//不能访问上一个节点 循环链表和双向链表可以解决
//亦或是再加一个指针找到前一个
void LinkListInsertAfter(Node* pos, Datatype data)
{Node* NewNode = NULL;if (NULL == pos){return;}// 将新节点插入到pos之后NewNode = LinkListCreat(data);NewNode->next = pos->next;pos->next = NewNode;
}

创建一个指针指向的是新开辟节点的地址,pos位置下一个节点的地址给到新节点指针域连接起来。最后将pos指针域放的是新节点的地址。

pos之前插入

//任意位置之前插入
void LinkListInsertBefore(Node** pplist, Node* pos, Datatype data)
{assert(pplist);//找到要插入的位置Node* Prior = *pplist;Node* NewNode = NULL;//链表为空我就调用我尾插这个方法就好了if (pos == *pplist) {LinkListPushFront(pos, data);}else if (NULL == pos){return;}else {NewNode = LinkListCreat(data);while (Prior->next != pos){Prior = Prior->next;}Prior->next = NewNode;NewNode->next = pos;}
}

先assert看一下链表存在不,定一个指针最后就是指向pos前面,还是分为那几个情况,链表为空,pos是*pplist直接就前插就好了,然后就是多个节点就是用这个prior来操作了,找到这个prior给他尾插一下,在连接起来。

希望本文对你有帮助,欢迎大佬来指指点点!

数据结构 严薇敏 单链表(无头结点)的实现(增 删 改 查)及其使用方法详解相关推荐

  1. 数据结构 严薇敏 堆 的实现及其使用方法详解

    1.堆的概念 将一个关键码的集合K = {k0 , k1,k2,k3--kn-1}把他所有元素按完全二叉树的存储方式放在一个一维数组中,并且满足双亲节点大于孩子节点,或者双亲节点小于孩子节点将根节点最 ...

  2. 表单的增 删 改 查

    django单表操作 增 删 改 查 一.实现:增.删.改.查 1.获取所有数据显示在页面上 model.Classes.object.all(),拿到数据后,渲染给前端;前端通过for循环的方式,取 ...

  3. 数据结构 严薇敏 顺序表的实现(增 删 改)及其使用方法详解

    时间复杂度 数据结构 时间复杂度和空间复杂度 目录 1.线性表 2.顺序表 2.1概念及结构 2.2 接口实现 SeqList.h SeqList.c 2.2.1初始化链表以及销毁链表的实现 初始化顺 ...

  4. 数据结构 严薇敏 队列 的实现及其使用方法详解

    目录 1.队列 1.1队列的概念及结构 1.2队列的实现 1.3接口以及实现 Queue.h Queue.c 申请一个队列的节点 初始化队列 入队列 出队列 查找队头元素 查找队尾元素 获取队列长度 ...

  5. 数据结构 严薇敏 栈 的实现及其使用方法详解

    目录 1.栈 1.1栈的概念及结构 1.2栈的实现 1.3接口以及实现 Stack.h Stack.c 栈的初始化 入栈 出栈 获取栈顶元素 获取栈中有效元素的个数 检测栈是否为空 栈的销毁 扩容 测 ...

  6. c语言栈是什么线性表,数据结构严薇敏——栈的顺序存储(C语言)

    栈是限定只能在表尾进行插入和删除操作的线性表. 栈的特点是后进先出. 它的顺序数据结构定义为 typedef struct SQSTACK { ElemType *base; ElemType *to ...

  7. c语言 链表 无头结点,C++ 单链表(无头结点)

    /* 单链表(无头结点) */ #include #include #include using namespace std; struct LNode { int data; // 数据域 LNod ...

  8. Mr.J--C语言头函数的建立(附严薇敏《数据结构》线性表代码)

    如何正确编写 C 语言头文件和与之相关联的 c 源程序文件 查看此文章需要有一定的C语言编程基础 首先就要了解它们的各自功能.要理解C 文件与头文件(即.h)有什么 不同之处,首先需要弄明白编译器的工 ...

  9. 狸猫换太子--删除无头单链表中结点

    狸猫换太子–删除无头单链表中结点 @(算法学习) 学习自<编程之美>. 很有意思的一种做法. 给定一个没有头指针的单链表,一个指针指向次单链表中的一个中间结点,删除此结点. 分析:这种根本 ...

  10. 数据结构练习:运用单链表实现图书管理系统(c/c++)(内含带头结点的单链表的基本操作)

    数据结构练习:运用单链表实现图书管理系统 正文 注意 部分功能运行展示 所包含头文件及结构体的定义 自定义函数 主函数 完整代码 结束语 正文 本程序使用带头节点的单链表存储结构实现,共有六个基本功能 ...

最新文章

  1. Socket 阻塞模式和非阻塞模式
  2. 用C语言扩展Python的功能
  3. Hdu 2089-不要62 数位dp
  4. MySQL TEXT数据类型的最大长度
  5. iOS底层原理探究-Runloop
  6. mysql聚簇索引 和主键的区别_[MySQL] innoDB引擎的主键与聚簇索引
  7. html时间自动,编辑自动结束时间.html
  8. 模糊搜索简单算法fuzzywuzzy
  9. gulp plugins
  10. 黑马程序员最新Python教程——第一阶段(2)
  11. 《SEM长尾搜索营销策略解密》一一1.1 做有个性的账户
  12. 微信公众号开发之iOS分享失败
  13. 2017 苹果强制https
  14. 浪潮服务器【磁盘阵列】故障修复
  15. OpenGL之FBO
  16. 英语语法回顾3——名词和名词性从句
  17. Jacobi迭代法分量形式matlab,实验4 Jacobi迭代法和GS迭代
  18. CF581B Luxurious Houses 模拟
  19. 怎么判断滤波器的低通、高通和带通?
  20. [机器学习]三行代码快速划分交叉训练中训练集和验证集

热门文章

  1. 贵港职称计算机考试网,贵港工程师职称等级时间
  2. 一套键鼠操控多台电脑--Mouse Without Borders 设置教程
  3. C#数字黑洞之一(西绪福斯黑洞:123数字黑洞)
  4. STM32采用串口DMA方式,发送数据
  5. 《东周列国志》第九十二回 赛举鼎秦武王绝胫 莽赴会楚怀王陷秦
  6. login.defs文件基础
  7. Effective Kotlin 中文版
  8. Android Studio编译错误:Suggestion: use tools:overrideLibrary=xxx.xxx.xxx to force usage
  9. 自定义View时,用到Paint Canvas的一些温故,自定义Loading控件(动画五,“六边形”的旋转跳跃)
  10. 生存分析之Cox模型简述与参数求解