定义:n个节点离散分配
彼此通过指针相连
每个节点只有一个前驱节点,每个节点只有一个后继节点
首节点没有前驱节点 尾节点没有后续节点
专业术语:
首节点:第一个有效的节点
尾节点:最后一个有效节点
头节点:头结点的数据类型和首节点类型一样,第一个有效节点之前的那个节点,头节点并不存放有效数据,加头节点的目的主要是为了方便对链表的操作
头指针:指向头节点的指针变量
尾指针:指向尾节点的指针变量
确定一个链表需要的参数:只需要一个参数即头指针 ,因为我们通过头指针我们可以推算出链表的其他所有信息
一个节点的生成Node
#include <stdio.h>
typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域
}NODE , *PNODE; //NODE等价于struct Node, PNODE等价于struct Node *
PNODE p = (PNODE)malloc(sizeof(NODE));
int main(void)
{
return 0;
}
分类:
单链表
双链表:每一个节点有两个指针域
循环链表:
非循环链表
算法:
遍历
查找
清空
销毁
求长度
排序
删除节点
插入节点
非循环单链表插入节点伪算法: q->pNext = p->pNext ; p->pNext = q;
非循环单链表删除节点伪算法: r = p->pNext ; p->pNext = p->pNext->pNext; free(r);
链表的优缺点:
优点:空间没有限制
插入删除元素很快
缺点
数据的存储很慢
链表的实现
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct Node
{
int data;//数据域
struct Node * pNext;//指针域
}NODE , *PNODE; //NODE等价于struct Node ,PNODE等价于struct Node *
//函数声明
PNODE creat_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int length_list(PNODE pHead);
bool insert_list(PNODE pHead, int pos, int val); //pos 从1开始
bool delete_list(PNODE pHead, int pos, int * pVal);
void sort_list(PNODE pHead);
int main(void)
{
PNODE pHead = NULL;
int val;
pHead = creat_list();//创建一个非循环单链表,并将该链表的头结点的地址赋给pHead
traverse_list(pHead);
if (is_empty(pHead))
printf_s("链表为空\n");
else
printf_s("链表不为空\n");
int len = length_list(pHead);
printf_s("链表的长度是%d\n", len);
sort_list(pHead); //排序
traverse_list(pHead);
if (insert_list(pHead, 3, 99))
{
printf_s("插入后的链表为:\n");
traverse_list(pHead);
}
if (delete_list(pHead, 4, &val))
{
printf_s("删除成功,您删除的元素是%d:\n",val);
}
else
{
printf_s("你删除的元素不存在\n");
}
system("pause");
getchar();
return 0;
}
PNODE creat_list(void)
{
int len; //有效节点的个数
int i;
int val; //临时存放用户输入的节点的值
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead)
{
printf_s("分配失败,程序终止!\n");
exit(-1);
}
printf_s("请输入您需要生成的链表节点的个数: len=");
scanf_s("%d", &len);
PNODE pTail = pHead;
pTail->pNext = NULL;
for (i = 0; i < len; ++i)
{
printf_s("请输入第%d个节点的值:", i + 1);
scanf_s("%d", &val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf_s("分配失败,程序终止!\n");
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext;
while (NULL != p)
{
printf_s("%d\n", p->data);
p = p->pNext;
}
return;
}
bool is_empty(PNODE pHead)
{
if (NULL == pHead->pNext)
return true;
else
return false;
}
int length_list(PNODE pHead)
{
PNODE p;
int len = 0;
p = pHead->pNext;
while (NULL != p)
{
++len;
p = p->pNext;
}
return len;
}
void sort_list(PNODE pHead)
{
int i, j, t;
int len = length_list(pHead);
PNODE p, q;
for (i=0,p = pHead->pNext; i < len - 1; ++i,p = p->pNext)
{
for (j = i + 1, q = p->pNext; j < len; ++j, q = q->pNext)
{
if (p->data > q->data)
{
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
}
//在pHead 所指向链表的第pos个节点的签名插入一个新的结点,值为val,并且pos从1开始
bool insert_list(PNODE pHead, int pos, int val)
{
int i;
PNODE p = pHead;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf_s("分配失败,程序终止!\n");
exit(-1);
}
for (i = 1; i < pos ; ++i)
{
p = p->pNext;
if (NULL == p->pNext)
{
printf_s("插入点超出链表长度!\n");
return false;
}
}
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
return true;
}
bool delete_list(PNODE pHead, int pos, int * pVal)
{
int i;
PNODE p = pHead;
for (i = 1; i < pos; ++i)
{
p = p->pNext;
if (NULL == p->pNext)
{
printf_s("删除点超出链表长度!\n");
return false;
}
}
PNODE q = p->pNext;
*pVal = q->data;
p->pNext = q->pNext;
free(q);
return true;
}