说明: 在此非常感谢笔记中涉及到的UP主上传的视频,因为此笔记是通过学习UP主的视频后根据视频记录的笔记。
建议:建议学习观看笔记中的视频时候一定要自己去通过键盘做笔记或者将代码在本地重现,不要试图通过大脑理解或者笔记本记录下来,因为很多时候通过键盘的输入可以加深对程序的理解和记忆,另一方面电子笔记利于随时随地的温习。
两个小时完全学会链表,学不会来找我,亲自教你~数据结构专场
-
内存4区:
- 代码区:函数代码–存放在代码区 函数名就是这个函数的地址。
- 全局区:全局的变量 字符串常量 初始化:int a;
- 栈区:5M–10M ,比较小,进肯能 告诉计算机 int double char 定义一个变量 c系统开辟 释放
- 堆区:自己定义大小,加载的数据用完后好要不要继续用,自己开辟,定义,释放
#include <stdio.h> #incldue <stdlib.h> int main() { int *p; //开辟内存, 开辟大小是字节 p = (int *)malloc(sizeof(int)); //释放内存 free(p); exit(0); }
-
数据结构:高速飙车,井然有序
- 用一套具体的方法来管理这些内存,高效,有序。
-
链表:火车站长的管理艺术。
-
c是面向过程的。
-
结点:每一块内存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4tdWa6L0-1610092841249)(en-resource://database/527:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ivki2hq2-1610092841251)(en-resource://database/528:1)] -
数据:每一个结点中存放数据
main.cpp
#include <stdio.h> #incldue <stdlib.h> #include 'list.h' void ShowData(Node* pnode) { printf("x = %d \t y = %d \n", pnode->data.x,pnode->data.y); } int main() { List *pList;//指针变量 ListInit(&pList);// Node* p = (Node*)malloc(sizeof(Node)); pnode->data.x = 10; pnode->data.y = 3; pnode->pnext = Null InserList(pList, pnode); TraverList(plist,ShowData); exit(0); }
list.cpp 写链表,此时数据,结点,无关
#include <stdio.h> #incldue <stdlib.h> #include 'list.h' //r如何判断链表是空的,初始化链表 /* * 功能:初始化链表,成功返回1,失败返回0 * 定义为二级指针是因为值传递时候c语言作用域问题,更改传递值的时候会借助指针和地址进行数值传递 */ int ListInit(List **pplist) { *(ppList) = (List*)malloc(sizeof(List)); if(*ppList ==NULL) return 0; else { (*ppList)->pfront = NULL; (*ppList)->prear = NULL; (*ppList)->count = 0; } return 1; } /* 判断链表是否为空 */ int IsEmpty(List* plist) { if(plist->count ==0) return 1; else return 0; } /* 插入结点 在plist这个链表中插入pnode结点 */ void InserList(List* plist,Node* pnode) { //尾插法 if(IsEmpty(plist)) { plist->pfront = pnode; } else { plist->prear->pnext = pnode; } plist->prear = pnode; plist->count ++; } //遍历链表 //留接口 //遍历pList这个链表 //void (*Traver)(Node* pnode) 函数指针 /* 指向指针的函数 函数 指针:Traver 指向:返回值类型为 void 参数为Node* */ void TraverList(List *pList,void (*Traver)(Node* pnode)) { Node *ptemp = plist->pfront;//ptemp指向第一个结点 int listsize = plist->count;//有几个结点 while(listsize) { Traver(ptemp); ptemp = ptemp->pnext; listsize--; } }
list.h
//数据 struct Data { int x; int y; }; //结点 1024 struct Node { Da1ta data;//数据 st0r uct Node *pnext; }; //链表 struct List { Node* pfront;//第一个结点的指针 Node* prear;//最后一个结点的指针 int count;//有多少指针 };
-
C语言核心重点知识教程——链表!理论加项目实乃学习效率最快
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//1 创建节点
//1.1 节点类型
struct Node{
int data;//存储数据
struct Node* pNext;//连接节点
};
//给类型定义
//typedefine struct Node node;
// 1.2 创建节点的函数
struct Node createNode(int);
//增
//尾增法
bool appenNodetoTree(struct Node** list, int);
//删
//改
//查
//从头到尾查
void travel(struct Node* head){
struct Node* p = head;
while(1){
if(NULL==p) break;
printf("%d",p->data);
p= p->pNext;
}
printf("\n");
}
int main(int argc, char* argv){
node * list = NULL;
bool ret;
struct node* pFind;
for(int i = 0; i<6;i ++){
ret = appenNodetoTree(&list,i);
if(ret)
printf("appendNodeTree :%d succed! \n");
else
printf("失败了 @-@ \n");
}
travel(list);
pFind = findNodePos(list,4);
if(pFind)printf("找到了:%d \n",pFind->data);
else
printf("not found\n");
eixt(0);
}
//制造节点函数
struct Node* createNode(int data){
//申请空间
struct Node* pNew = (struct Node *)malloc(sizeof(struct Node));
if(NULL == pNew) return NULL;
//把数据设置好
pNew->data = data;
pNew->pNext = NULL;
return pNew;
}
//尾增法
bool appenNodetoTree(struct Node** list, int data){
//防御性编程
if(NULL == list) return false;
if(* list == NULL){
*list = createNode(data);
return ture;
}
//找到尾部
struct Node* pTail = list;
/*
while(1){
if(NULL==pTail->pNext) break;
pTail= pTail->pNext;
}
*/
while(pTail->pNext) pTail = pTail->pNext;
//添加数据
pTail-pNext = createNode(data);
return true;
}
//查找
struct Node* findNodePos(struct Node* head, int findData){
while(head){
if(head->data == findData) return head;
head = head->pNext;
}
return NULL;
}
C语言 链表基础知识清晰讲解(黑马)
- 链表是由一系列节点组成的,每个节点包含两个域,一个是数据域,数据域用来保存用户数据。另外一个书指针域,保存下一个节点的地址。
- 链表在内存中是非连续的。
- 链表在指定位置插入和删除都不需要移动元素,只需要修改指针即可
- 查找效率低一些,相对于数组
- 链表相对于数组,多了指针域空间开销
- 拿到链表第一个节点,就相当于拿到了整个链表。
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//链表结点类型定义
struct LinkNode
{
int data;
struct LinkNode * next;
}
viod test()
{
struct LinkNode node1 = {10, NULL};
struct LinkNode node2 = {20, NULL};
struct LinkNode node3 = {30, NULL};
struct LinkNode node4 = {40, NULL};
struct LinkNode node5 = {50, NULL};
struct LinkNode node6 = {60, NULL};
node1.next = &node2;
node2.next = &node3;
node3.next = &node4;
node4.next = &node5;
node5.next = &node6;
//如何遍历链表
//先定一个辅助指针变量
struct LinkNode *pCurrent
}
int main()
{
exit(0);
}
##### main.c
void test()
{
//初始化链表
struct LinkNode *header = Init_LinkList();
//打印链表
Foreach_LinkList(header);
//插入数据
InsertByValue_LinkList(header,300,6);
//打印链表
Foreach_LinkList(header);
//清空链表
Clear_LinkList(header);
RemoveByValue_linList(head,200);
Foreach_LinkList(header);
//销毁链表
Destroy_LinkList(header);
}
int main()
{
test();
exit(0);
}
###### LinkList.h
//定义节点数据
struct LinkNode
{
int data;
struct LinkNode *next;
}
//初始化链表
struct LinkNode *Init_LinkList();
//在值为oldval的后面插入一个新的数据newval
viod InsertByValue_LinkList(struct LinkNode *header,int oldval,int newval);
//删除值为val的节点
void RemoveByValue_linList(sturct LinkNode *header,int delValue);
//遍历
void Foreach_LinkList(struct LinkNode *header);
//销毁
void Destroy_LinkList(struct LinkNode *header);
//清空、
void Clear_LinkList(struct LinkNode *header);
###### LinkList.c
//初始化链表
struct LinkNode *Init_LinkList()
{
//创建头结点
sturct LinkNode *header = malloc(sizeof(struct LinkNode));
header->data = 1;
header->next = NULL;
//尾部指针
struct LinkNode *pRear = header;
int val = 1;
while(true)
{
printf("请输入插入的数据: \n);
scanf("%d",&val);
if(val == 1)
{
break;
}
//先创建新节点
struct LinkNode *newnode = malloc(sizeof(struct LinkNode));
newnode->data = val;
newnode->next = NULL;
//新节点插入列表中、
pRear->next = newnode;
//更新尾部指针只想
pRear = newnode;
}
return header;
}
//在值为oldval的后面插入一个新的数据newval
viod InsertByValue_LinkList(struct LinkNode *header,int oldval,int newval)
{
if(NULL == header)
{
return;
}
//两个辅助指针变量
struct LinkNode *pRrev = header;
struct LinkNode *pCurrent = pPrev->next;
while(pCurrent->data != NULL)
{
if(pCurrent->data == oldval)
{
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
if(NULL == pCurrent)
{
return;
}
//先创建新节点
struct LinkNode *newnode = malloc(sizeof(struct LinkNode));
newnode->data = newval;
newnode->next = NULL;
//新节点插入到链表中
newnode->next = pCurrent;
pPrev->next = newnode;
}
//删除值为val的节点
void RemoveByValue_linList(sturct LinkNode *header,int delValue);
{
if(NULL == header)
{
return;
}
//两个辅助指针变量
struct LinkNode *pPrev = header;
struct LinkNode *pCurrent = pPrev->next;
while(pCurrent != NULL)
{
if(pCurrent->data == delValue)
{
break;
}
//移动两个辅助指针
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
if(NULL == pCurrent)
{
return;
}
//重新建立待删除节点的前驱和后继节点的关系
pPrev->next = pCurrent->next;
//释放删除节点内存
free(pCurrent);
pCurrent = NULL;
}
//遍历
void Foreach_LinkList(struct LinkNode *header)
{
if(NULL == header)
{
return;
}
//辅助指针变量
struct LinkNode *pCurrent = header->next;
while(pCurrent != NULL)
{
printf("%d",pCurrent->data);
pCurrent = pCurrent->next;
}
}
//销毁
void Destroy_LinkList(struct LinkNode *header)
{
if(NULL == header)
{
return;
}
//辅助指针变量
struct LinkNode *pCurrent = header->next;
while(pCurrent != NULL)
{
//先保存下一个节点地址
struct LinkNide *pNext = pCurrent->next;
//释放当前节点
free(pCurrent);
//指针向后移动
pCurrent= pNext;
}
}
//清空、
void Clear_LinkList(struct LinkNode *header)
{
if(NULL == header)
{
return;
}
//辅助指针变量
struct LinkNode *pCurrent = header->next;
while(pCurrent != NULL)
{
//先保存一下当前节点的下一个节点
struct LinkNode *pNext = pCurrent->next;
//释放当前节点内存
free(pCurrent);
//pCurrent指向下一个节点
pCurrent = pNext;
}
header->next = NULL;
}