动态规划入门详解 内含12道经典动态规划编程题

article/2025/10/7 4:13:46

动态规划入门详解

一 什么是动态规划??

算法导论中介绍,动态规划和分治方法类似,都是听过子问题的解来解决原问题。下面说一下这2者之间的分别,分治方法将原问题划分为互不相交的子问题,而后将子问题组合之后求出原问题的解,而动态规划是相反的,动态规划利用子问题之间的重叠,写出原问题和子问题之间的状态转移方程,转化为更小的子问题的求解,直到到达边界条件为止,有点类似于递归。

①动态规划和分治的区别 分治的子问题是不重叠的 如归并排序 ,快排 动态规划是有重叠的
②贪心和动态规划的区别 贪心是自顶向下的 ,不会等子问题求解完毕后求原问题

二 动态规划问题求解的一般的步骤 (具体的步骤千变万化,但遵循的思路大体一致)

首先 要知道动态规划是用来解决最优解的(最大,最小,最长等问题)

1 将原问题转化为一个个小问题,而且每一个小问题之间是有重叠的,而且这些小问题满足最优的子结构 (就是这些小问题对后面的没有重叠的影响 且 这小问题的最优解的组合可以原问题的最优解)
2用数组dp存这些小问题的答案,确定存的内容是什么 可以比较直观的解题,dp中的状态必须有无后效性,意思就是已经记录的状态不会发生改变,而且而且未来的状态只能在现在的状态中组合产生。(就是转移方程)
3找到这些小问题的边界,注意保证,在这个边界下,大问题求解的每一步所要用到的小问题的结果都是已经存入数组dp里,否则无法保证最后问题求解的准确性,(2,3一般是一起完成的)
4找到原问题和小问题之间的联系,,建立状态转移方程,
5先写出赋值边界的代码,而后写出状态转移的代码
……

下面用题目来看动态规划
题目1 第一题较为简单和直观
斐波那契数列 f0=1,f1=1,f2=2,f3=2 f4=5…… fn=f(n-1)+f(n-2)
求fn的递归写法

int f(n)
{if(n==0 || n==1)  return 1;else return f(n-1)+f(n-2);
}

递归写法很简单1 但是效率很低很低,因为当n变大时,存在很多重复的计算 例如 求f10
求f10 那就要求f9 和f8 求f9 要求f8和f7 求f8要求f7和f6 …… 可以看出 f8已经求了2次了 易得越小的n求得重复的次数越多,因为每一个大的数,都是通过小的得到的

下面看一下 动态规划的解法 因为fn由相邻的2个数得到 那就用dp[n] 存所有的已经计算出来的f【n】的结果 dp【n】== -1表示没有计算

int f(n)
{if(n==0 || n==1) return 1;if(dp[n] != -1)  return dp[n];else{dp[n]=dp[n-1] +dp[n-2];  //关键语句return dp[n];}}

乍一看这和递归没有什么区别;看关键语句,这里的求法,其实和递归是完全不一样的 因为这里用的是数组里面的值的相加就OK了
而递归用的调用函数去求解 ,在动态规划中,每一个fn的值求一次就被记录了 之后用到就直接用,而递归是每一次都要求一遍 时间复杂度是完全不一样的
相当于用一个On的空间,把指数级的时间复杂度降到了线性级 这是很合算的。。。。。。。。。。。。。

题目二 数塔问题
先看题目:如下图(图片来自百度图片)是一个数塔,从顶部出发在每一个节点可以选择向左或者向右走,一直走到底层, 求找出一条路径,使得路径上的数字之和最大

在这里插入图片描述
显然 用f[i][j]表示i行 j个 ,从1开始
那么f【1】【1】的最大和 就是max(下面2个的最大和)+ f[1][1]; 显然可以划分为子问题 而且有重复存在
那么令dp【i】【j】记录到 f【i】【j】的最大值和
则边界条件为最下层的dp值 所有的上层可以由下层得到
状态转移方程: dp【i】【j】= max(dp【i+1】【j】 ,dp【i+1】【j+1】)+f【i】【j】
代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;const int maxn =1010;
int f[maxn][maxn],dp[maxn][maxn];
int main()
{int n;scanf("%d,&n");for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){scanf("%d",&f[i][j]);}}//边界for(int j=1;j<=n;j++){dp[n][j]=f[n][j];}//从第一层往上计算n-1层for(int i=n-1;i>=1;i--){for(int j=1;j<=i;j++){dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];}}printf("%d",dp[1][1]);return 0;
}

这个问题中,求dp【1】【1】转化为求子问题的最优解 而且可以由子问题的最优解的得到原问题的解 所以可解

题目三 最大连续子序列和
题目描述:给定一个数字序列A1,A2,…,An,求i,j(1≤i≤j≤n),使得Ai+,…,+Aj最大,输出这个最大和。
例子
-2 11 -4 13 -5 -2

显然11+(-4)+3=20为和最大的选值情况,因此最大和为20
解题思路:用dp【i】存以i为结尾的最大的的子序列的和 则每一个dp【i】和dp【i-1】有关 dp【i】=max(dp【i-1】+A【i】,A【i】)
因为是连续的 要么就是加上前一个之后更大,要么就是自己单独一个 那么dp中最大的那个就是答案,因为每一个都和前一个
相关,所以边界就是第一个 即dp【0】。到此,边界和状态转移方程都有了
代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;const int maxn=10010;
int A[maxn],dp[maxn];
int main()
{int n;cin>>n;for(int i=0;i<n;i++){cin>>A[i];}dp[0]=A[0];//边界for(int i=1;i<n;i++)  //状态方程{dp[i]=max(A[i],dp[i-1]+A[i]);}int k=0;for(int i=0;i<n;i++){if(dp[i]>dp[k])k=i;}printf("%d",dp[k]);return 0;
}

对于本题 ,我们可以看出如何设置状态和状态转移方程才是动态规划最难的地方,在不同的题目中是千变万化的,只有不停的积累的练习才能掌握,至少现在我是这么理解的。

题目四 最长不下降子序列

  1. 问题描述:在一个数字序列中,找到一个最长的子序列(可以不连续),使得这个子序列是不下降的(非递减的)

例如现有序列A = {1,2,3,-1,-2,7,9}(下标从1开始)它的最长不下降子序列是{1,2,3,7,9}长度为5,还有一些子序列是不下降子序列,比如{1,2,3}、{-2,7,9}但是不是最长的,输出最长的长度

本题算是上一题的进化版 因为可以不连续,所以dp【i】和之前的所有的dp都有关系 且每一个dp确定之后是不会变的
所以可以用动态规划求解
所以边界是每一个自己是一个序列 dp【i】=1;
状转移方程:dp【i】=max(1,dp【j】+1) j是在i之前的所有值的枚举
代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;const int N=100;
int A[N],dp[N];
int main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>A[i];}int ans=-1;//记录最大值长度for(int i=1;i<=n;i++){dp[i]=1;//初始条件for(int j=1;j<i;j++){if(A[j]<=A[i] && dp[j]+1 > dp[i])  //选最大的那个{dp[i]=dp[j]+1;}}ans=max(ans,dp[i]);}printf("%d",ans);return 0;
}

题目五 最长公共子序列
题目描述:给定两个字符串,求解这两个字符串的最长公共子序列(可以不连续)。比如字符串1:BDCABA;字符串2:ABCBDAB
则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA
就是求2个序列中 公共最多的子序列的长度 输出长度即可
这一题的难度又比前面2题要难 因为在本题中的 数组有2个,是公共的解 ,而且比较难想到用动态规划求解
步骤一 假设i,j分别表示数组1和数组2现在的位置 在求dp数组时,相同的i不同的j是可能会变化的 ,所以dp应该是二维的 设 dp【i】【j】,i是第一个数组的位置 j是第二个数组的位置
步骤二 本题很自然想到dp’中放的就是最长长度
步三 :易得 dp【i】【j】可dp【i-1】【j-1】得到 若A【i】==B【j】 那直接长度加一就好
若不相等,那是无法延长的 那就是dp【i】【j-1】 和dp【i-1】【j】中大的那一个
那边界就是dp【i】【0】和dp【0】【j】 0< i<n,0<j<m

代码如下

#include <iostream>
#include <cstdio>
#include<cstring>
#include <algorithm>
using namespace std;const int N=100;
char A[N],B[N];
int dp[N][N];
int main()
{int n;gets(A+1);//从下标1开始读入gets(B+1);int lena=strlen(A+1);//也从1开始计长度int lenb=strlen(B+1);for(int i=0;i<=lena;i++)  //边界{dp[i][0]=0;}for(int j=0;j<=lenb;j++){dp[0][j]=0;}for(int i=1;i<=lena;i++) //状态方程{for(int j=1;j<=lenb;j++){if(A[i] == B[j]){dp[i][j]= dp[i-1][j-1]+1;}else{dp[i][j]=max(dp[i-1][j],dp[i][j-1]);}}}printf("%d",dp[lena][lenb]);//最后的就是答案return 0;
}

题目六 最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。 你可以假设 s 的最大长度为1000。
回文的主要特点就是 如果一个大字符串是回文 那么这个大字符串包含的小字符串也是回文 直到最后只有一个字符或2个一样的字符

对于字符串str,假设dp[i,j]=1表示str[i…j]是回文子串,那个必定存在dp[i+1][j-1]=1。这样最长回文子串就能分解成一系列子问题,可以利用动态规划求解了,需要一层层分解子问题 ,那么数组和数组中存的内容就确定了。接下来构造状态转移方程,
在这里插入图片描述
因为边界是长度为1 和2的子串 所以按照长度递推(这就是动态规划的递推写法 从边界出发的原理)
代码如下

#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
const int maxn=1010;char S[maxn];
int dp[maxn][maxn];
int main()
{gets(S);int len = strlen(S),ans=1;//ans表示最长的长度memset(dp,0,sizeof(dp));for(int i=0;i<len;i++)//边界{dp[i][i]=1;if(S[i] == S[i+1]){dp[i][i+1]=1;ans=2;}}for(int l=3;l<=len;l++)//用长度开始递推  {for(int i=0;i+l-1<len;i++){ // 起始点和终点在范围内int j=i+l-1;if( S[i]==S[j] && dp[i+1][j-1]== 1){dp[i][j]=1;ans=l;}}}cout<<ans;return 0;
}

对于最长的回文串的问题 最好的求解算法是manacher算法 有兴趣可以自己查阅一下 (On级别的时复)

题目七 爬楼梯问题
题目来源LeetCode
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
易得 dp【n】=dp【n-1】+dp【n-2】‘’
代码如下

    int climbStairs(int n) {int dp[100];dp[1]=1;  //边界dp[0]=1;if(n<=1) return dp[n];else{for(int i=2;i<=n;i++){dp[i]=dp[i-1]+dp[i-2];}}return dp[n];

题目八 爬楼梯问题进阶版
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 或3……或n 个台阶。你有多少种不同的方法可以爬到楼顶呢?
假设dp【i】表示总共为i阶的跳发
那么 dp【i】=dp【i-1】+dp【i-2】+……dp【1】+dp【0】;
dp【i-1】=dp【i-2】+… dp【1】+dp【0】;
所以 dp【i】=2dp【i-1】;这就是状态转移方程

代码如下

int climbStairs(int n) {int dp[100];int total=1;for(int i=1;i<n;i++){total=2total;}return total;

题目九
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路
求f(i) 有2种情况 要么竖着放第一个 要么横着放第一个
竖着的话 f(i)=f(i-1) 横着放 f(i)=f(i-2)
所以 f(i)=f(i-1)+f(i-2);这就是斐波那契数列 代码就不写了哈哈哈哈哈

题目十
最长递增子串的扩展 众所周知,牛妹是一个offer收割姬,这次面试她遇到了这样的一个问题。 给了一个序列,让找出最长的“凸子序列” 何为“凸子序列”:数列中有一个xi,使得所有x0<x1<x2….xi-1<xi且xi>xi+1>xi+1>….>xn eg:12345431,是山峰序列,12345234不是山峰序列 注:单调递增或单调递减序列也算山峰序列;单独一个数是长度为1的山峰序列
思路:用两个dp数组分别从前往后求最长的递增子串与从后往前求。最后将两个dp数组相加减一取得的最大值就是结果。

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const int Max = 1110;
int dp[Max],dp2[Max];
int A[Max];
int main(){fill(dp,dp+Max,1);fill(dp2,dp2+Max,1);int n;scanf("%d",&n);for(int i = 0;i<n;++i){scanf("%d",&A[i]);}for(int i = 0;i<n;++i){for(int j = 0;j<i;++j){if(A[i]>A[j]){dp[i] = max(dp[i],dp[j]+1);}}}for(int i = n-1;i>=0;--i){for(int j = n-1;j>i;--j){if(A[i]>A[j]){dp2[i] = max(dp2[i],dp2[j]+1);}}}int ans = 1;for(int i = 0;i<n;++i){ans = max(ans,dp[i]+dp2[i]-1);}printf("%d",ans);return 0;
}

背包问题

背包问题是动态规划中一个比较常见的问题 ,比较灵活多变 ,这里介绍比较简单的2种 01背包问题和完全背包问题
题目十一
01背包问题
有n个物品,它们有各自的体积w【】和价值c【】,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?其中每一种物品只有一件

用dp【i】【v】表示前i件物品 恰好放入容量为v的背包中所获得的最大的价值;
那么考虑 i时,有2中 ,c表示价值 w表示体积
①放入第i物品放入 那么转化为前 i-1 件物品 恰好放入容量为v-w【i】的背包的最优解,所以等于 dp【i-1】【v-w【i】】+c【i】
②不放入 那就是dp【i-1】【v】
所以转移方程 dp【i】【v】= {以上2种情况里大的那一个};
因此求解是 一直递推i-1 直到i=0,那边界就是dp【0】【v】=0;0<= v <=V;
因为dp【i】【v】表示的是恰好为v的情况,所以要枚举dp【n】【v】 0<= v <=V,才可以得到最优解 因为背包的体积不一定要全部用完
代码如下

//边界
for(int i=0;i<=v;i++)
{dp[0][i]=0;
}
for(int i=0;i<=n;i++){  //状态方程for(int v=w[i];v<=V;v++){ //注意v要从w【i】开始  不然后面-w【i】的那个数组会越界了dp[i][v]=max(dp[i-1][v],dp[i-1][v-w[i]] + c[i]);}
}

滚动数组优化背包问题

时间复杂度和空间复杂度都是是Onv,下面对空间复杂度进行优化;
由于在计算时dp【i】【v】时 只需要dp【i-1】【v】和dp【i-1】【v-w【i】】的数据 ,但是在计算dp【i+1】时所有dp【i-1】【】的数据就不用了 这样就可以开一个一维数组dp【v】,就是省掉【i】。但是在枚举v时 是要逆序的
为什么计算时要逆序枚举?计算顺序所决定!请看下图:
在这里插入图片描述
如当i=1时,f(10)=max{f(10),f(10-v[1])+w[1]}=max{f(10),f(7)+w[1]}=max{0,4}=4

即f(10)依赖的是f(10)和f(7)的值,需要注意的是,此时的f(10)和f(7)是i=0时的f(10)和f(7),如果使用二维数组存储,无需担心覆盖问题,对体积的枚举逆序或正序都可,但是如果使用一维数组,若正序枚举会先计算f(7),那么,再计算f(10)时,i=0时的f(7)已被覆盖矣!

使用这样的以为数组的方法被叫做滚动数组,就是在求解的过程中,计算出一个的dp[i][v] 就把之前的dp[i-1][v]给覆盖了 因为求出i v之后,i-1的那个数组时不会再用掉了 因为求解时,要用到【i-1】【v】之前的数组 所以只能从右往左遍历 才能保证需要的左边的那个数组不被提前覆盖
优化后的代码如下

//边界
for(int i=0;i<=v;i++)
{dp[0][i]=0;
}
for(int i=0;i<=n;i++){  //状态方程for(int v=V;v>=w[i];v--){ dp[v]=max(dp[v],dp[v-w[i]] + c[i]);  //后面的dp【v】表示的就是未更新的i-1}
}
int max=0;
for(int v= 0;v<=v;v++){  //找最大值  以为背包面积体积可能不会用完if(dp[v] >max){ max=dp[v];}
}

以上就是关键的代码 完整的代码就不写了 加上输入输出和初始化而已。。。。。。。。。。。

注意:滚动数组的使用条件是每一层只和上一层有关 ,使用滚动数组的时候,确定i时,枚举v的时候,一定要逆序 ,原因如上。

题目十二 完全背包问题

有n个物品,它们有各自的体积w【】和价值c【】,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?其中每一种物品有无穷件。。。
和上一题的区别在于 其中的每种物品有无穷建
思想如下
用dp【i】【v】表示前i件物品 恰好放入容量为v的背包中所获得的最大的价值;
那么考虑 i时,有2中 ,c表示价值 w表示体积
①放入第i物品,这里的处理和01问题是不一样的 因为在01问题中 放入就代表必须转移到i-1中
但是在这里,放入之后还是可以继续放,那就不会到i-1 依旧停留在i 因为i是可以再放的,由容量限制 最终还是有限的
所以dp【i】【v】= dp【i】【v-w【i】】+c【i】
②不放入,和01问题显然是一样的 那就是dp【i-1】【v】
所以转移方程 dp【i】【v】= {以上2种情况里大的那一个};
边界就是dp【0】【v】=0;0<= v <=V;

同样用滚动数组优化

for(int i=0;i<=n;i++){  //状态方程for(int v=w[i];v<=V;v++){ dp[v]=max(dp[v],dp[v-w[i]] + c[i]);  //后面的dp【v】表示的就是未更新的i-1}
}

优化之后你会发现 状态方程和01问题是一样的 ,这个很容易理解 但是存在的不同之处是对v的遍历必须是正序的,而01问题必须是逆序的。那么问题就来了 这是为什么呢????
其实这很好理解**,因为完全背包问题 用的是 dp[v-w[i]],;和dp[i-1][v] 是在dp【i】【v】的左边的数组 所以从左往右遍历 才能保证左边的数组存在。所以必须从左到右**、

**

总结

**:动态规划的问题其实和递归很像 一般情况下 自顶向下的递归的问题 都可以转化为自低向上的动态规划问题,一层层叠出最后的结果
边界就是递归是的出口条件 反过来递推而已 ,在此时,看求dp是用到哪些量 依据这个来进行空间复杂度的优化

若有2个字符串或者数组之间的问题 那一搬就用dp[i] [j]来表示A【i】到B【j】区间之间的问题 就是一个区间dp 公共子序列和回文串就是这样的,回文串的求解方式比较特别 这是需要记住的方法
最后,在做题时,一般用dp要考虑题目中的状态需要用几维来表示 每一维就是一个含义先定义弄清楚
之后就是对每一维采取恰好为i,恰好为j 或者前i 前j 然后找到边界 (一般是端点)


http://chatgpt.dhexx.cn/article/qvYvUYhq.shtml

相关文章

【刷题日记】动态规划经典题目

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…

Linux命令-sftp文件传输

搭建SFTP服务详见博文&#xff1a;https://blog.csdn.net/cen50958/article/details/90722874 连接SFTP 可使用&#xff1a;sftp --help 查看SFTP的连接参数 [rootstudy ~]# sftp --help usage: sftp [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config] [-o ssh_option…

Linux命令(三):SFTP

目录 1、登录 2、文件上传 3、文件下载 4、删除文件/文件夹 5、实战 1、登录 sftp userip 你要用sftp, 当然得登录到sftp服务器&#xff0c; 在linux的shell中执行上面的命令后&#xff0c; linux shell会提示用户输入密码&#xff0c; 我们就输入password吧。 这样就成功…

Linux常用命令——sftp命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) sftp 交互式的文件传输程序 补充说明 sftp命令是一款交互式的文件传输程序&#xff0c;命令的运行和使用方式与ftp命令相似&#xff0c;但是&#xff0c;sftp命令对传输的所有信息使用ssh加密&#xff0c;它还…

SFTP命令常用操作

SFTP相关(等价于rz/sz&#xff0c;此方式适用于没有工具的情况下&#xff0c;前提是保证sftp默认端口22开放) lcd 本地文件路径 进入到本地的某个目录下 cd 远程文件路径 进入到远程的某个目录下 lpwd 显示本地的当前目录的路径 pwd 显示远程的当前目录的路径 这里只介绍常…

SFTP基本功之get、put命令操作

简述 在安装好linux系统之后&#xff0c;开始不断安装部署各种工具&#xff0c;其中很多工具版本太老使得无法使用wget下载&#xff0c;而只能用put命令从本地硬盘中上传之linux系统内安装&#xff0c;而当我编写系统克隆mongodb数据库时&#xff0c;又了解到了get命令&#x…

SFTP命令的使用,sftp传文件

背景&#xff1a;从Windows系统向类unix系统传送文件&#xff0c;使用Windows系统自带的SFTP命令进行文件传送(不用下载F开头&#xff0c;X开头的ftp工具) 背景分割线 上干货&#xff1a;1.WinX&#xff0c;按A&#xff0c;输入SFTP root192.168.162.236 回车&#xff1b; &…

SFTP登录及命令行用法

sftp命令行登录过程 ① sftp xxx.xxx.xxx.xxx 登录&#xff08;默认root用户&#xff09;&#xff0c;若指定用户 sftp bluexxx.xxx.xxx.xxx 进行登录&#xff08;blue为用户名&#xff09; ② 登录成功后&#xff0c;会提示输入 密码 ③ 然后&#xff0c;可进入目录&#xf…

SFTP命令用法(上传和下载 )

一、SFTP SFTP是Secure File Transfer Protocol的缩写&#xff0c;安全文件传送协议。可以为传输文件提供一种安全的网络的加密方法。SFTP与FTP有着几乎一样的语法和功能。SFTP为SSH的其中一部分&#xff0c;是一种传输档案至Blogger伺服器的安全方式。其实在SSH软件包中&…

Linux基础命令 sftp命令的使用

SFTP&#xff08;Secure File Transfer Protocol&#xff0c;安全文件传输协议&#xff09;是一种基于可靠数据流&#xff08;data stream&#xff09;&#xff0c;提供文件存取和管理的网络传输协议&#xff0c;与 FTP 协议相比&#xff0c;SFTP 在客户端与服务器间提供了一种…

sftp常用命令介绍

sftp常用命令&#xff1a; 1. sftp 登录sftp服务器 sftp userip ​​​​​​ 如需要看全部命令&#xff1a;则使用help即可 2. pwd和lpwd 、 ls和lls 、cd和lcd 等 sftp登录之后默认操作是远程服务器&#xff0c;当需要操作本地时&#xff0c;就需要在前边加“l”&#…

Linux中使用sftp的常用命令

前言 在数据库远程维护的过程中&#xff0c;经常需要和本机进行数据的交互&#xff0c;常用的交互方式为ftp&#xff0c;但是这种方式需要确保21端口和ftp服务都存在。在远程访问服务器的时候大部分使用ssh来进行连接&#xff0c;其使用的端口为22端口&#xff0c;与之共用的数…

单链表的基本操作-查找

【问题描述】 实现有头结点单链表查找算法&#xff1a;根据关键字值查找其在单链表中的位置(第一次出现的位置)。 【输入形式】 第一行输入整数n&#xff08;n不大于1000&#xff09;&#xff0c;表示单链表长度&#xff1b; 第二行输入若干个整数&#xff08;以非法整数或…

单链表的基本操作(C语言+图解分析)

目录 一、单链表的建立 1、头插法 2、尾插法 二、插入结点操作 三、删除节点操作 四、单链表操作的一些常见问题 1、结构体变量和结构体指针的区别&#xff1f; 2、什么时候要malloc&#xff1f; 3、形参里面出现了取地址符(&)&#xff0c;有什么作用&#xff1f;…

c++单链表的基本操作(全)

俩个基本插入方法 #include <bits/stdc.h> using namespace std; typedef struct LNode { int date; //节点的数据域 struct LNode *next; //节点的指针域 }LNode,*LinkList; // LinkList 为指向结构体LNode的指针类型bool Initlist_L(LinkList &L) …

单链表的基本操作(学习总结)

单链表的声明初始化&#xff1a; 1.头文件&#xff1a; 这里不做太多说明&#xff0c;是学习C语言的基础。 #include<stdio.h> #include<stdlib.h> 2.结构声明&#xff1a; 数据结构算法中&#xff0c;每个表&#xff0c;树&#xff0c;图类的工具组都需要定义它…

Java 实现单链表的基本操作

顺序表&#xff1a;物理上逻辑上都连续&#xff1b; 链表&#xff1a;物理上不一定连续&#xff0c;逻辑上一定连续的。 链表的概念及结构 概念&#xff1a;连表示一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是用过链表中的引用链接次序实现的…

数据结构:单链表的基本操作

单链表是一种链式存取的数据结构&#xff0c;用一组地址任意的存储单元存放线性表中的数据元素。这组存储单元可以是连续的&#xff0c;也可以是不连续的。链表中的数据是以结点来表示的&#xff0c;一个结点包含数据域和指针域&#xff0c;数据域用来存储结点的值&#xff0c;…

python实现单链表的基本操作

一、单链表 单向链表&#xff08;单链表&#xff09;是链表的一种&#xff0c;其特点是链表的链接方向是单向的&#xff0c;对链表的访问要通过顺序读取从头部开始。单链表是一种链式存取的数据结构&#xff0c;用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是…

Java实现单链表及其基本操作

目录 什么是单链表&#xff1f; 带头结点的单链表 不带头结点的单链表 模拟实现不带头结点的单链表 定义结点类 初始化 头插法创建单链表 尾插法创建单链表 打印单链表 单链表的查找 获取单链表的长度 按位置寻找前驱结点 单链表的插入 修改指定位置的值 按…