《算法笔记》7.3 链表
一.链表的概念
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 链表相关推荐
- 《算法笔记》之链表二叉树
链表 之前找工作的时候,受益于算法笔记,这次开始复习,也是从这本书入手,打算重新学习算法,因此从最基础的开始,只要我们去一点一点付出,最后一定结果不会差.加油,道虽远,行将就至. 链表有若干个节点组成 ...
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
- 左程云算法笔记(四)哈希表和有序表的使用、链表
左程云算法笔记(四) 哈希表的使用 有序表的使用 链表 单链表反转 (LC206) 双向链表反转 打印两个有序链表的公共部分 合并两个有序链表(LC21) 判断一个链表是否为回文结构 (LC234) ...
- 数据结构与算法笔记(十五)—— 散列(哈希表)
一.前沿 1.1.直接寻址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术.假设某应用要用到一个动态集合,其中每个元素都有一个取自全域U={0,1,-,m-1)的关键字,此处m是一个不很大 ...
- 《algorithm-note》算法笔记中文版正式发布!
无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...
- 【算法】《algorithm-note》算法笔记中文版正式发布!
无论是做机器学习.深度学习.自然语言处理还是其它领域,算法的重要性不言而喻!吃透算法底层原理.掌握算法数学推导和代码实现,对提高自己的硬核实力来说非常重要!今天给大家推荐一个超赞的开源算法笔记!中文版 ...
- 算法笔记(JavaScript版)——排序
算法笔记(JavaScript版)--排序 本文内容根据Rebert Sedgewick和Kevin Wayne的<算法(第四版)>整理,原代码为java语言,自己修改为JavaScrip ...
- 算法笔记(胡凡)学习笔记@Kaysen
本文旨在记录算法笔记学习过程中的收获和一些知识点,部分易错知识点只针对个人而言,CCF-CSP考试冲鸭!!! Chapter 2 C/C++快速入门(易错知识点) 2.1 基本数据类型 变量定义注意区 ...
- 数据结构与算法笔记(青岛大学王卓老师视频)
写在前面的话: 因为在学习数据结构之前,学习过一年的算法,所以有一些基础,一些我觉得 没必要的代码或知识就没写上,记得多是一些知识点,写的可能对于别人来说 很难接受,望谅解.我学习算法是在Acwing ...
- codeup墓地目录(算法笔记习题刷题笔记)
在线codeup contest 地址:http://codeup.cn/contest.php Contest100000575 - <算法笔记>3.1小节--入门模拟->简单模拟 ...
最新文章
- pandas高级处理-合并
- faiss简介及示例
- 单片机温度控制系统DS18B20
- 作为大数据和云计算学习的一个序吧
- 了解LSTM和GRU
- cf1555D. Say No to Palindromes
- MySQL和SQL Server数据库基本语句总结(二)
- 我的开发笔记---UIPageControl的详细使用
- 开局说丑说拒绝,开售抢的贼快!iPhone11预约超百万
- C++冒泡排序(包含初级、正宗及改进三种实现)
- 剑指offer——面试题61:按之字形顺序打印二叉树
- Oracle Real Application Clusters (RAC)
- 7-8 mmh学长的Excel表格 (20分)
- MVC学习笔记----缓存
- XMind8 pro 免费破解版!速度
- python自学1:更改excel内容案例及技术总结
- 各大搜索引擎蜘蛛名称
- DF-GAN: A Simple and Effective Baseline for Text-to-Image Synthesis论文解读
- K-means原理、优化及应用
- 备案不用关闭网站的9种技巧