链表
1.内存4区
- 代码区
1.函数代码存放在代码区
2.函数名就是这个函数的地址
- 全局区
存放全局变量
- 栈区
用于定义变量,直接定义的变量都存在这里
5-10M,内存很小。尽可能不去使用栈区,而去使用堆区。
- 堆区
自己确定有多大
确定装什么数据
用完之后要不要继续用这块内存
1.头文件
要使用堆区内存,必须包含“动态内存分配这一头文件”
#include<stdlib.h>
2.malloc();函数
从而我们可以使用malloc();函数
malloc函数的功能是开辟内存空间。
使用:
*1.*malloc(数字);
开辟几个字节函数就在括号中写几
malloc(sizeof(int));
malloc(4);
2.(类型 *)malloc(数字);
开辟的内存给什么类型就用什么类型的关键字
例如:
(int *)malloc(4);
(float *)malloc(4);
#include<stdlib.h>
int *p;//在栈区定义指针
p = (int *)malloc(4);//在堆区开辟内存,指针p指向这段内存
//几级地址就加几个*号
//malloc的堆区内存不会自己释放,必须自己释放
C
free§;
C++
new和delete
2.链表
链表:一种数据结构
结点:每一块开辟的内存
数据:内存里存放的数据
C++
#include "list.h"//list.h是自己写的头文件
//初始化链表
/*
功能:初始化链表 成功返回1 失败返回0
/*
初始化
定义数据结构体Data
struct Data
{
int x;//两个数据
int y;
}
定义结点结构体Node
struct Node
{
Data data;//数据
struct Node *pnext;//指向下一个结点的指针
}
注意:
-
单链表中只有一个data和pnext
-
双链表中有一个pprev,data,和pnext,即比单链表结点多了一个头指针
定义结构体类型List
front(头结点),rear(尾结点),count(节点数)
struct List
{
Node *pfront;//指向第一个结点的指针
Node *prear;//指向最后一个结点的指针
int count;//用于计算结点数
}
从而定义初始化链表函数
3.链表的操作
- 初始化链表
int ListInit(List **pplist)//pplist是指向指针的指针
{
*(pplist) = (List*)malloc(sizeof(Node));//给链表开辟空间
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;
}
-
反转
-
插入
尾插法:让原有的最后一个结点pnext指向新的节点pnode;链表中的prear也指向pnode
头插法:让pnode指向第一个结点的pnext;链表中的pfront指向pnode
//这里使用尾插法
void InsertList(List* plist),Node* pnode)//在plist链表中插入pnode这个结点
{
if (IsEmpty(plist))
{
plist->pfront = pnode;
plist->prear = pnode;
plist->count++;//空链表时的操作
}
else
{
plist->prear->pnext = pnode;
plist->prear = pnode;
plist->count++;//不为空链表时的操作
}
}
可以使用for循环指定插入节点数
-
删除
-
遍历链表
留接口 ,通过接口遍历
void TraverList1 (List * plist2, void(* Traver3)(Node* pnode))