目录
一.单链表相关概念
定义 |
|
特点 |
|
头结点和头指针的区别 |
|
引入头结点 的优点 |
|
二.单链表基本操作
1、采用头插法建立单链表 | 2、采用尾插法建立单链表 | |
代码 | LinkList List_HeadInsert(LinkList &L) { //逆向建立单链表 LNode *s; int x; L = (LinkList) malloc(sizeof(LNode)); //创建头结点 L->next = NULL;/初始为空链表 scanf("%d", &x); //输入节点的值 while (x != 9999) {//输入9999表示结束 s = (LNode *) malloc(sizeof(LNode)); //创建新节点 s->data = x; s->next = L->next; L->next = s; //将新节点插入表中, L为头指针 | LinkList List_TailInsert(LinkList &L) { //正向建立单链表 int x; L = (LinkList) malloc(sizeof(LNode)); LNode *s, *r = L; // r为表尾指针 scanf("%d", &x); //输入节点的值while (x != 9999) {//输入9999表示结束 s = (LNode *) malloc(sizeof(LNode)); //创建新节点 s->data = x; r->next = s; r = s; // r指向新的表尾节点 scanf("%d", &x); } r->next = NULL; //尾节点指针置空 |
3、删除节点操作 | 4、插入节点操作 | |
代码 | p = GetElem(L, i - 1); //查找删除位置的前驱结点 q = p->next; //令q指向被删除节点 p->next = q->next; //将*q节点从链中断开 free(q) //释放节点的存储空间 | p = GetElem(L, i - 1); //查找插入位置的前驱结点 s->next = p->next; p->next = s; |
5、求表长操作(不含头结点) | ||
代码 |
|
三.双链表
为什么引入双链表? |
| |
双链表的插入操作 | s->next = p->next; //将节点*s插入到*p之后 p->next->prior = s; s->prior = p; p->next = s; | |
双链表的 删除操作 | p->next = q->next; //删除节点*q q->next->prior = p; free(q) | |
单/双链表常考结论 |
|
四.循环链表
循环单链表 |
|
循环双链表 |
|
常考结论 |
|
五.静态链表
定义 |
|
结构描述 | #define Maxsize 50 typedef struct { //定义单链表节点类型 ElemType data; //数据域 int next; //下一个元素的数组下标 } SLinkList[Maxsize]; |
常考结论 | 静态链表需要分配较大空间, 插入和删除不需要移动元素的线性表 |
六.顺序表与链表比较
顺序表 | 链表 | |
读取方式 | 能随机存取 | 不能随机存取 |
逻辑结构与 物理结构 | 相邻 | 不一定相邻 |
空间分配 | 需要预先按需分配存储空间 | 可以在需要时申请分配,只要 内存有空间就可以分配 |
按值查找 | 无序为O(n); 有序可采用 折半查找O(logn) | O(n) |
按序号查找 | O(1) | O(n) |
插入 | O(n) | O(1) |
删除 | O(n) | O(1) |
七.怎样选取存储结构
顺序表 | 链表 | |
基于存储的考虑 | 难以估计时不宜用顺序表, 顺序表存储密度高 | 链表不用估计,但存储密度较低 |
基于运算的考虑 | 若经常按序号访问,选择顺序表 |
|
基于环境的考虑 | 顺序表容易实现 | 链表是基于指针的 |
----ssss