1、定义:
n个结点离散分配
彼此通过指针相连,每个结点只有一个前驱结点/后续结点
首结点没有前驱结点,尾节点无后续结点
2、专业术语:
头结点:不存储有效数据(加头节点目的主要是方便链表操作)
头指针:指向头节点的指针变量(存放头节点的地址)
首结点 尾结点
尾指针:指向尾节点的指针
3、确定一个单链表需要几个参数:
1、头指针
通过头指针可以推算出链表的其它所有信息
4、一个结点如何生成:
结点的组成:数据域、指针域
typedef struct Node{
int data; //数据域
struct Node * pNext; //指针域
}NODE, *PNODE; //NODE等价于struct Node,PNODE等等价于struct Node *
5、链表的分类:
单链表
双链表:每个结点有两个指针域
循环链表:能通过任何一个结点找到其它所有的结点
非循环链表:
6、算法(伪算法):
遍历、查找、清空、销毁、求长度、排序、删除结点(需要手动释放内存)、插入结点
第一步:定义结点
链表是由一个个结点连接而成的,所以首先需要使用结构体定义一个结点,单链表只有数据域和指针域,故结构体中有两个变量:
typedef struct NODE {
int data;
struct NODE *pNext;
}NODE, *PNODE;
第二步:创建单链表
创建单链表需要知道单链表 结点个数以及每个结点的 数据域的值
int len; //用来存放有效节点的个数
int i;
int val; //用来临时存放用户输入的结点的值,
- 首先分配一个NODE类型大小的空间,并把分配空间的首地址强制转换成NODE *类型,然后定义一个指针指向这个分配空间,这个指针就是头指针。
PNODE pHead = (PNODE)malloc(sizeof(NODE)); // pHead指向头节点
if (NULL == pHead) // 内存分配时必须判断是否成功
exit(-1);
- 接着定义一个指针pTail也指向头节点,并将头节点指针域设置为空,至此完成了空表的建立
PNODE pTail = pHead; // pTail也指向头节点
pTail->pNext = NULL; // 先创建一个空链表
即创建一个空表,如下图
- 先输入数据域的值,然后新建结点来保存数据域的值,并将前驱结点依次指向后驱结点
scanf("%d", &len);
for (i = 0; i < len; i++) {
scanf("%d", &val);
PNODE pNew = (PNODE)malloc(sizeof(NODE)); //pNew是新的结点
if (NULL == pNew)
exit(-1);
pNew->data = val; //给新结点赋数值域
pTail->pNext = pNew; //指向新节点
pNew->pNext = NULL; //给新结点赋指针域
pTail = pNew; //pTali时刻指向尾指针域
}
注:其中pTail一直指向末尾结点
创建单链表全部代码如下:
PNODE creat_list(void) {
int len; //用来存放有效节点的个数
int i;
int val; //用来临时存放用户输入的结点的值,
/*分配一个不存放有效数据的头节点*/
PNODE pHead = (PNODE)malloc(sizeof(NODE)); //pHead指向头节点
if (NULL == pHead) //内存分配时必须判断是否成功
exit(-1);
PNODE pTail = pHead; //pTail也指向头节点
pTail->pNext = NULL; //先创建一个空链表
scanf("%d", &len);
for (i = 0; i < len; i++) {
scanf("%d", &val);
PNODE pNew = (PNODE)malloc(sizeof(NODE)); //pNew是新的结点
if (NULL == pNew)
exit(-1);
pNew->data = val; //给新结点赋数值域
pTail->pNext = pNew; //指向新节点
pNew->pNext = NULL; //给新结点赋指针域
pTail = pNew; //pTali时刻指向尾指针域
}
return pHead; // 最后返回头节点地址
}