一、离散存储【链表】
链表定义:
n个节点离散分配,
彼此通过指针相连,
每个节点最多只有一个 前驱节点和后续节点,
首节点没有前驱节点,尾节点没有后续节点。
专业术语:
首节点:第一个存放有效数据的节点。
尾节点:最后一个存放有效数据的节点。
头结点:没有存放数据或者链表大小的一个节点,首节点前面的一个节点。其数据类型和首 节点一样。主要为了方便对链表的操作。
头指针:指向头节点的指针变量。
尾指针:指向尾节点的指针变量。
如果希望通过一个函数来对链表进行处理,我们至少需要接受链表的哪些参数:
只需要一个参数,即头指针,有了头指针我们就可以推算出其他所有的信息。
一个链表节点表示为:
#include <stdio.h>
typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域,pNext指向一个和它本身存储指向下一个节点的指针
}DODE, *PNODE; //NODE等价于struct Node, PNODE等价于struct Node *
PNODE p=(PNODE)malloc(sizeof(NODE)); //将动态分配的新节点的地址赋给P
free p;//删除p指向节点所占的内存,不是删除p本身所占内存
p->pNext; //p所指向结构体变量中的pNext成员本身
int main()
{
return 0;
}
链表的分类:
单链表:单向的链表,指针域只指向后面或者前面
双链表:每一个节点有两个指针域,分别指向前节点和后节点
循环链表:能通过任何一个节点找到其他所有的节点
非循环链表:不是循环的链表都是非循环链表
非循环单链表插入节点伪算法讲解
/*如图所示,有一个链表,其中一个指针P指向其中一个节点,
现在有一个Q指向的节点,要求把它插入P指向节点的后面,
如何实现?*/
//主要有以下两种方式
1、r=p->pNext; p->pNext = q; q->pNext = r;
2、q->pNext = p->pNext; p->pNext = q;
//p->pNext这个整体表示节点的指针域
非循环单链表插入节点伪算法讲解
/*如图所示,有一个链表,其中一个指针P指向其中一个节点,
要求把它后面一个节点删除,如何实现?*/
1、p->pNext = p->pNext->pNext;
/*这样容易造成内存泄漏,原因是将P指向节点后面的那个节点的地址改写
所以就找不到后面那个节点,然后不能及时释放内存*/
正确写法如下
r = p->pNext;
p->pNext = p->pNext ->pNext;
free(r)