一.链表的概念
1.分为数据域和指针域:

struct node {typename datd; //数据域node* next; //指针域
};

2.链表分为带头结点和不带头结点(头结点:data 不存放数据,next 指向第一个数据域有内容的结点);

二.为新结点申请动态内存空间
1.malloc函数:(C语言)
头文件:#include<stdlib.h>
返回类型:同变量类型的指针;
基本用法:typename* p = (typename*)malloc(sizeof(typename));
示例:

int* p = (int*)malloc(sizeof(int));

malloc函数向内存申请一块大小为 sizeof(int) 的空间,并返回指向这块空间的指针,此时这个指针是未确定类型的 void*,在最前面加上(int*) 强制转换成 int*;
申请失败:返回空指针NULL并赋值给 p(当申请了较大的动态数组时);

2.new运算符:(C++)
基本用法:typename* p = new typename;
示例:

int* p = new int;

申请失败:启动 C++ 异常处理机制而不是返回空指针 NULL;

3.内存泄漏
指使用 malloc 和 new 开辟出来的内存空间在使用后没有释放,导致后来无内存可分配;
如何释放空间:
1).free函数(对应 malloc函数):释放内存空间,并将 p 指向空地址 NULL;

free(p);

2).delete运算符(对应 new运算符):

delete(p);

三.基本操作
1.创建链表:

#include<stdio.h>
#include<stdlib.h>
struct node {int data;node* next;
};node* create(int Array[]) {node *p, *pre, *head; // pre保存当前结点的前驱结点 head = new node;head->next = NULL;pre = head;for(int i = 0; i < 5; i++) {p = new node;p->data = Array[i];p->next = NULL;pre->next = p;pre = p;}return head;
}int main() {int Array[5] = {5, 3, 6, 1, 2};node* L = create(Array);L = L->next;while(L != NULL) {printf("%d", L->data);L = L->next;}return 0;
}

2.查找元素

int search(node* head, int x) {int count = 0;node* p = head->next;while(p != NULL) {if(p->data == x) count++;p = p->next;}return count;
}

3.插入元素

void insert(node* head, int pos, int x) {node* p = head;for(int i = 0; i < pos - 1; i++) p = p->next;node* q = new node;q->data = x;q->next = p->next;p->next = q;
}

4.删除元素

void del(node* head, int x) {node* p = head->next;node* pre = head;while(p != NULL) {if(p->data = x) {pre->next = p->next;delete(p);p = pre->next;}else {pre = p;p = p->next;}}
}

四.静态链表
原理:建立一个结构体数组,令数组下标直接表示结点的地址;

struct Node {typename data;int next;
}node[size];node[11111] = 22222;// 下标为此结构体地址,内容为下一个结构体的地址
node[22222] = 33333;
node[33333] = -1;

注意:不要把结构体类型名(Node)和结构体变量名(node)取成相同的名字,防止 sort 函数使用时出错;

五.题目
*通用步骤:
1.定义静态链表:

struct Node {int address;typename data;int next;XXX; //Node的一个性质,例如设置成 bool flag
}node[maxn];

2.对XXX进行初始化:

for(int i = 0; i < maxn; i++)node[i].XXX = 0;

3.遍历链表——> 对XXX标记 + 计数:

int p = head, count = 0;
while(p != -1) {XXX = 1;count++;p = node[p]->next;
}

4.定义静态链表时数组下标是address,会使得数组不连续,这步的目的在于把有效结点移动到最前面,下标变成 0~count,address 储存在 struct 中:

bool cmp(Node a, Node b) {if(a.XXX == -1 || b.XXX == -1) return a.XXX > b.XXX;else //第二级排序
}

1.PATA1032
思路:
先遍历第一个链表,标记每个结点(不要另开数组,直接在结构体里定义 flag);

注意:
1).不能通过判断 -1 出现的次数为二决定输出 -1,为什么?
2).scanf 输入%c 时可以使用空格,如果有空格的话则必须加上空格;
3).使用 %05d 输出地址,可以使不足五位的地址整数高位补零;

代码:

#include<cstdio>
#include<cstring>
using namespace std;const int maxn = 100010;
int n;struct Node {char data;int next;bool flag;
}node[maxn];int main() {int head1, head2;int count1 = 0;scanf("%d%d%d", &head1, &head2, &n);int adr, next_adr;char x;for(int i = 0; i < n; i++) {scanf("%d %c %d", &adr, &x, &next_adr);node[adr].data = x;node[adr].next = next_adr;node[adr].flag = false;}int p;for(p = head1; p != -1; p = node[p].next)node[p].flag = true;for(p = head2; p != -1; p = node[p].next) {if(node[p].flag == true) {break;}}if(p != -1) printf("%05d\n", p);else printf("-1\n");return 0;
}

2.PATA1052
思路:
直接舍弃链表这个结构——>不行,因为给出的 n 个 Node 可能不全为有效结点,需要用链表结构得到有效结点个数——> node 下标还是应该用 address,排序范围为 0~ maxn,不能下标用 0~n,排序范围为 0 ~n,否则在while(p != -1) { node[p].flag = true; count++; p = node[p].next; }会很麻烦;

注意:
if(count == 0) printf("0 -1\n");的情况;

代码:

#include<cstdio>
#include<algorithm>
using namespace std;const int maxn = 100010;
struct Node {int data;int address;int next;bool flag;
}node[maxn];bool cmp(Node a, Node b) {if(a.flag == false || b.flag == false) return a.flag > b.flag;else return a.data < b.data;
}int main() {int n, head;scanf("%d%d", &n, &head);int adr, next_adr, x;for(int i = 0; i < n; i++) {scanf("%d%d%d", &adr, &x, &next_adr);node[adr].data = x;node[adr].address = adr;node[adr].next = next_adr;}for(int i = 0; i < maxn; i++) node[i].flag = false;int p = head, count = 0;while(p != -1) {node[p].flag = true;count++;p = node[p].next;}if(count == 0) printf("0 -1\n");else {sort(node, node + maxn, cmp);printf("%d %05d\n", count, node[0].address);for(int i = 0; i < count; i++) {if(i != count - 1) printf("%05d %d %05d\n", node[i].address, node[i].data, node[i + 1].address);else printf("%05d %d -1\n", node[i].address, node[i].data);}}return 0;
}

3.PAT B1025
思路:
如何把链表按照顺序排列:不用另开数组,记录下每个 node 的顺序 order,用 sort 函数排序,得到 node[0~count];

注意:
这种倒来倒去的我就不太会,尤其是确定数组的下标;

代码:

#include<cstdio>
#include<algorithm>
using namespace std;const int maxn = 100010;
struct Node {int address;int data;int next;int order;bool flag;
}node[maxn]; bool cmp(Node a, Node b) {if(a.flag == false || b.flag == false) return a.flag > b.flag;else return a.order < b.order;
}int main() {for(int i = 0; i < maxn; i++) {node[i].flag = false;}int head, n, k;scanf("%d%d%d", &head, &n, &k);int adr, x, next_adr;for(int i = 0; i < n; i++) {scanf("%d%d%d", &adr, &x, &next_adr);node[adr].address = adr;node[adr].data = x;node[adr].next = next_adr;}int p = head, count = 0;while(p != -1) {node[p].order = count++;node[p].flag = true;p = node[p].next;}sort(node, node + maxn, cmp);for(int i = 0; i < count; i = i + k) {if(i + k - 1 < count) {Node temp;for(int j = i; j < (2 * i + k) / 2; j++) {temp = node[j];node[j] = node[2 * i + k - 1 - j];node[2 * i + k - 1 - j] = temp;}for(int m = i; m < i + k - 1; m++) {node[m].next = node[m + 1].address;}if(i != 0) node[i - 1].next = node[i].address;if(i + k - 1 == count - 1) node[i + k - 1].next = -1;if(count - (i + k) < k && count - (i + k) < k > 0) node[i + k - 1].next = node[i + k].address;}else break;}for(int i = 0; i < count; i++) {if(i == count - 1) printf("%05d %d -1\n", node[count - 1].address, node[count - 1].data);else printf("%05d %d %05d\n", node[i].address, node[i].data, node[i].next);}return 0;
}

《算法笔记》7.3 链表相关推荐

  1. 《算法笔记》之链表二叉树

    链表 之前找工作的时候,受益于算法笔记,这次开始复习,也是从这本书入手,打算重新学习算法,因此从最基础的开始,只要我们去一点一点付出,最后一定结果不会差.加油,道虽远,行将就至. 链表有若干个节点组成 ...

  2. 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...

    来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...

  3. 左程云算法笔记(四)哈希表和有序表的使用、链表

    左程云算法笔记(四) 哈希表的使用 有序表的使用 链表 单链表反转 (LC206) 双向链表反转 打印两个有序链表的公共部分 合并两个有序链表(LC21) 判断一个链表是否为回文结构 (LC234) ...

  4. 数据结构与算法笔记(十五)—— 散列(哈希表)

    一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...

  5. 《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  6. 【算法】《algorithm-note》算法笔记中文版正式发布!

    无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...

  7. 算法笔记(JavaScript版)——排序

    算法笔记(JavaScript版)--排序 本文内容根据Rebert Sedgewick和Kevin Wayne的<算法(第四版)>整理,原代码为java语言,自己修改为JavaScrip ...

  8. 算法笔记(胡凡)学习笔记@Kaysen

    本文旨在记录算法笔记学习过程中的收获和一些知识点,部分易错知识点只针对个人而言,CCF-CSP考试冲鸭!!! Chapter 2 C/C++快速入门(易错知识点) 2.1 基本数据类型 变量定义注意区 ...

  9. 数据结构与算法笔记(青岛大学王卓老师视频)

    写在前面的话: 因为在学习数据结构之前,学习过一年的算法,所以有一些基础,一些我觉得 没必要的代码或知识就没写上,记得多是一些知识点,写的可能对于别人来说 很难接受,望谅解.我学习算法是在Acwing ...

  10. codeup墓地目录(算法笔记习题刷题笔记)

    在线codeup contest 地址:http://codeup.cn/contest.php Contest100000575 - <算法笔记>3.1小节--入门模拟->简单模拟 ...

最新文章

  1. pandas高级处理-合并
  2. faiss简介及示例
  3. 单片机温度控制系统DS18B20
  4. 作为大数据和云计算学习的一个序吧
  5. 了解LSTM和GRU
  6. cf1555D. Say No to Palindromes
  7. MySQL和SQL Server数据库基本语句总结(二)
  8. 我的开发笔记---UIPageControl的详细使用
  9. 开局说丑说拒绝,开售抢的贼快!iPhone11预约超百万
  10. C++冒泡排序(包含初级、正宗及改进三种实现)
  11. 剑指offer——面试题61:按之字形顺序打印二叉树
  12. Oracle Real Application Clusters (RAC)
  13. 7-8 mmh学长的Excel表格 (20分)
  14. MVC学习笔记----缓存
  15. XMind8 pro 免费破解版!速度
  16. python自学1:更改excel内容案例及技术总结
  17. 各大搜索引擎蜘蛛名称
  18. DF-GAN: A Simple and Effective Baseline for Text-to-Image Synthesis论文解读
  19. K-means原理、优化及应用
  20. 备案不用关闭网站的9种技巧

热门文章

  1. 总结i2mago的杨智谋的分享
  2. python_turtle_四叶草、普通爱心、渐变小心心
  3. java抽象类可以实现接口吗?
  4. flash AIR 通过BitmapData生成图片到本地
  5. 用AUTODESK MeshMixer对三角形mesh进行remesh
  6. three.js之材质
  7. 电路设计——接地的三种方法
  8. windows 删除之前的蓝牙耳机
  9. 计算机助理证书有用吗,请问计算机助理级职称证书
  10. 一名合格的电子工程师英文水平应该达到什么标准?