重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
按照你的要求,不使用数组。
创新互联服务紧随时代发展步伐,进行技术革新和技术进步,经过10多年的发展和积累,已经汇集了一批资深网站策划师、设计师、专业的网站实施团队以及高素质售后服务人员,并且完全形成了一套成熟的业务流程,能够完全依照客户要求对网站进行做网站、网站设计、建设、维护、更新和改版,实现客户网站对外宣传展示的首要目的,并为客户企业品牌互联网化提供全面的解决方案。
我的思路,起点货物狼、羊、白菜,人一直在开船,通过递归函数,每次靠岸尝试装卸货方案,直到找满足条件的方案。将可行方案存放在结构链表中形成操作流水打印。
人狼羊菜存储方式模拟4位2进制,用1111表示,每位表示一个单位,1存在,0不存在。
#includestdio.h
#includemalloc.h
typedef enum{false,true}bool;
typedef struct opRecord//用结构链表记录操作流水
{
int p1_take;//p1载货值
int p1_goAd;//p1卸货值
int p2_take;//p2载货值
int p2_goAd;//p2卸货值
int cen;//递归层号
struct opRecord *next;
}OPR;
OPR *oprHead;
OPR *oprTail;
char *getName(int b);//获取对应名称
int beEaten(int p1,int p2);//检查是否发生被吃事件,发生返回1,未发生返回0
int toShip(int *p1,int *p2,int *ship,bool f);//递归函数:上船人及任意一组合,返回状态,1:方案可行;0:方案不可行
int getFist(int pn);//获取物品组合中第一个
void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen);//将有效操作添加进日志,cen相同,将视为修改覆盖
void printfLog();//打印操作流水
OPR *findLogBycen(int cen);//通过cen查找流水。 有返回节点指针。无返回NULL
int count=1;
int flag=0;//标识变量=1成立; =0不成立
int cen=0;
int main()
{
int p1=111,ship=1000,p2=0000;//p1,p2分别表示两岸,4位数每一位分别表示人狼羊菜,位数值1表示存在,0表示不存在
oprHead=(OPR *)malloc(sizeof(OPR));
oprHead-next=NULL;
oprTail=NULL;
printf("河岸有人、狼、羊、白菜要过河,船每次载人及一物,为避免人上船后狼吃羊或羊吃菜\n开始生成方案:\n\n");
if(toShip(p1,p2,ship,0))
{
printf("\n开始生成结果报告:\n");
printfLog();
}
else
printf("无可行方案!!\n");
return 0;
}
void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen)//将有效操作添加进日志,cen相同,将视为修改覆盖,
{
OPR *oprNew=findLogBycen(cen);
if(oprNew==NULL)//通过查找。确认无记录,新增记录
{
oprNew=(OPR *)malloc(sizeof(OPR));
oprNew-p1_take=p1_take;
oprNew-p1_goAd=p1_goAd;
oprNew-p2_take=p2_take;
oprNew-p2_goAd=p2_goAd;
oprNew-cen=cen;
oprNew-next=NULL;
if(oprHead-next==NULL)
oprHead-next=oprNew;
else
oprTail-next=oprNew;
oprTail=oprNew;
}
else//查找发现已有记录,修改
{
oprNew-p1_take=p1_take;
oprNew-p1_goAd=p1_goAd;
oprNew-p2_take=p2_take;
oprNew-p2_goAd=p2_goAd;
}
}
OPR *findLogBycen(int cen)//通过cen查找流水。 有返回节点指针。无返回NULL
{
OPR *headSave=oprHead;
while(headSave-next!=NULL)
{
if(headSave-next-cen==cen)
return headSave-next;
headSave=headSave-next;
}
return NULL;
}
void printfLog()//打印操作流水
{
OPR *headSave=oprHead;
int p1_take,p1_goAd,p2_take,p2_goAd,cen,p1TOp2,p2TOp1;
while(headSave-next!=NULL)
{
p1_take=headSave-next-p1_take;
p1_goAd=headSave-next-p1_goAd;
p2_take=headSave-next-p2_take;
p2_goAd=headSave-next-p2_goAd;
cen=headSave-next-cen;
if(p1_take0 || p1_goAd0)
p1TOp2=1;
else
p1TOp2=0;
if(p2_take0 || p2_goAd0)
p2TOp1=1;
else
p2TOp1=0;
printf("操作流水%2d:",cen);
printf("%s%s",p1TOp20?"从p1":"",p2TOp10?"从p2":"");
printf("%s%s",p1_goAd0?getName(p1_goAd):"",p1_goAd0?"下船":"");
printf("%s%s",p1_take0?getName(p1_take):"",p1_take0?"上船":"");
printf("%s%s",p2_goAd0?getName(p2_goAd):"",p2_goAd0?"下船":"");
printf("%s%s",p2_take0?getName(p2_take):"",p2_take0?"上船":"");
if(headSave-next-next!=NULL)
printf("。之后行驶方向:%s%s\n",p1TOp20?"p1-p2":"",p2TOp10?"p1-p2":"");
else
printf("\n");
headSave=headSave-next;
}
}
char *getName(int b)//获取对应名称
{
if(b==1000)
return "人";
else if(b==100)
return "狼";
else if(b==10)
return "羊";
else if(b==1)
return "菜";
return "";
}
int toShip(int *p1,int *p2,int *ship,bool f)//递归函数:上船人及任意一组合;lastTake:上一次承载物体,首次调用传0;f=0:p1-p2方向;1:反向。返回状态,1:方案可行;0:方案不可行;
{
int take=-1,goAd,gdflag=1,cenSave;//take:上船物体。 goAd:下船物体。gdflag:标识变量,p2判断能否直接下船,1能0不能
cenSave=++cen;
while(1)
{
goAd=*ship-1000;
if(f==0)//准备p1往p2
{
if(take==-1)
take=getFist(*p1);
*p1-=take;
*p1+=goAd;
gdflag=1;//标识置1,等到p2首先尝试直接卸货
}
else//准备p2往p1
{
if(take==-1 gdflag==0)
{
take=getFist(*p2);
printf("开始尝试替换货物:\n");
}
if(gdflag==1)//如果p2可以直接卸货
*p2+=goAd;
else//如果不能直接卸货,尝试带走一个同时卸货
{
*p2-=take;
*p2+=goAd;
}
}
printf("递归层级%d:假设%s从%s上船。%s下船,%s方向行驶。\n",cenSave,take0?getName(take):"无货物",f==0?"p1":"p2",goAd!=0?getName(goAd):"无货物",f==0?"p1往p2":"p2往p1");
if(beEaten(*p1,*p2))//如果发生被吃,假设失败,还原数据,选择下一假设
{
if(f==0)
{
*p1+=take;
*p1-=goAd;
}
else
{
if(gdflag==1)//p2点确定不能直接卸货,还原数据,标识置0
{
printf("----不能直接卸货,货物%s回到船上。",getName(goAd));
*p2-=goAd;
gdflag=0;
continue;
}
else//不能直接卸货并尝试替换货物失败,选择下一个货物替换
{
*p2+=take;
*p2-=goAd;
}
}
if(take==1)
{
printf("本次靠岸无可行的装卸方案,返回层级%d!\n",cenSave-1);
return 0;
}
take=take/10;//尝试选择下一个货物
continue;
}
else
{
if(f==1 gdflag==1)//p2直接卸货假设成立船清空
*ship=1000;
else
*ship=1000+take;//换货假设成立货物装船
if(*p1==0)//如果已经完全转移
{
printf("所有货物过河成功!!\n");
return 1;
}
if(f==0)
addLog(take,goAd,0,0,cenSave);//生成流水日志
else
addLog(0,0,take,goAd,cenSave);//生成流水日志
if(toShip(p1,p2,ship,f==0?1:0))
{
return 1;
}
else//由于下级失败,本回合重新选择
{
gdflag=0;
continue;
}
}
}
}
int getFist(int pn)//获取物品组合中第一个
{
int i,count=0;
while(1)//上船物体从岸上第一个物体开始选择
{
if(pn=1)
break;
pn=pn/10;
count++;
}
for(i=0;icount;i++)
pn=pn*10;
return pn;
}
int beEaten(int p1,int p2)//检查是否发生被吃事件,发生返回1,未发生返回0
{
int ren=0;
if(p1==110 ++ren==1)
printf("----河岸p1狼把羊吃了!重新选择\n");
if(p2==110 ++ren==1)
printf("----河岸p2狼把羊吃了!重新选择\n");
if(p1==11 ++ren==1)
printf("----河岸p1羊把菜吃了!重新选择\n");
if(p2==11 ++ren==1)
printf("----河岸p2羊把菜吃了!重新选择\n");
return ren;
}
好久不写了
写一个程序,建立N元整型数组,然后输入查找的整数x,查找x是否包含在数组中,查找用函数实现,若查找成功,返回x在数组中的第一次出现的下标,查找失败,返回-1
源程序:
#include"stdio.h"
#define N 10
int locate(int a[N],int x)
{int h,r,m;
h=0;r=N-1;m=(h+r)/2;
while(h=rx!=a[m])
if(xa[m]) {r=m-1;m=(h+r)/2;}
else {h=m+1;m=(h+r)/2;}
if(hr) return -1; /*查找失败,返回-1*/
return m; /*查找成功,返回有效下标m */
}
void upinsert(int a[],int i) /*插入排序 (升序)*/
{int x,j;
x=a[i];j=i-1;
while(j=0a[j]x) {a[j+1]=a[j];j--;}
a[j+1]=x;
}
void main()
{int a[N],x,k,n;
printf("input %d integers:\n",N);
for(k=0;kN;k++) {scanf("%d",a+k);upinsert(a,k);}
printf("input x=") ;scanf("%d",x);
n=locate(a,x);
for(k=0;kN;k++) printf("%4d",a[k]);
printf("\n fist position=%d\n",n);
}
没有错误,我试过了
这个程序没错,我在VC上可以运行。这个程序实际上就是将一个字符串中指定位置上的字符删除掉。下面解释两个语句的意思。
假如输入:
abcdefg
4
输出:
abcefg
p+=position-1; 相当于 p = p + (position-1); 也就是将指针 p 从字符串首部移动到 (position - 1)个位置。一开始 p 指向 'a',现在 p 指向 'd'。
while((*p++=*(p+1))!='\0'); 相当于
while(p!='\0'){ *p=*(p+1); p++;} 也就是不断地将后一个元素取代前一个元素,'d'被'e'取代,'e'被‘f'取代,如此直到字符串末尾。
1, 找到VS的cl.exe所在目录,把这目录复制下来:
我的VS2008的CL.EXE目录是在E:\Program Files\Microsoft Visual Studio 9.0\VC\bin,
VS2010可以类似的找到..
在'我的电脑'上点右键,
选右键菜单'属性'-'高级'-'环境变量',
在弹出的环境变量设置框里找"PATH"这个变量, (在用户变量或系统变量里都可以)
然后在"PATH"的值后面,用分号分隔,
把将才找到的路径串复制进去,选确定.
2, 重新运行CMD开启新的命令窗.
3, 输入cl回车检查PATH路径是否生效.
//以上步聚是设置环境变量,只需设一次以后就好用了.以后每次要命令行下编译C++程序,就从下面第4步开始.
4, 输入vcvars32 ,运行cl.exe同一路径下的vcvars32.bat,设置其它环境变量.
5, 写一个helloworld程序,保存成hello.cpp, cl hello.cpp回车试试编译正常不. 如果成功,则生成hello.exe文件.
//-----------------------------------------------------------
C/C++ 编译器选项
-优化-
/O1 最小化空间 /Op[-] 改善浮点数一致性
/O2 最大化速度 /Os 优选代码空间
/Oa 假设没有别名 /Ot 优选代码速度
/Obn 内联展开(默认 n=0) /Ow 假设交叉函数别名
/Od 禁用优化(默认值) /Ox 最大化选项。(/Ogityb2 /Gs)
/Og 启用全局优化 /Oy[-] 启用框架指针省略
/Oi 启用内部函数
-代码生成-
/G3 为 80386 进行优化 /Gh 启用 _penter 函数调用
/G4 为 80486 进行优化 /GH 启用 _pexit 函数调用
/G5 为 Pentium 进行优化 /GR[-] 启用 C++ RTTI
/G6 对 PPro、P-II、P-III 进行优化 /GX[-] 启用 C++ EH (与 /EHsc 相同)
/G7 对 Pentium 4 或 Athlon 进行优化 /EHs 启用 C++ EH (没有 SEH 异常)
/GB 为混合模型进行优化(默认) /EHa 启用 C++ EH(w/ SEH 异常)
/Gd __cdecl 调用约定 /EHc extern "C" 默认为 nothrow
/Gr __fastcall 调用约定 /GT 生成纤维安全 TLS 访问
/Gz __stdcall 调用约定 /Gm[-] 启用最小重新生成
/GA 为 Windows 应用程序进行优化 /GL[-] 启用链接时代码生成
/Gf 启用字符串池 /QIfdiv[-] 启用 Pentium FDIV 修复
/GF 启用只读字符串池 /QI0f[-] 启用 Pentium 0x0f 修复
/Gy 分隔链接器函数 /QIfist[-] 使用 FIST 而不是 ftol()
/GZ 启用堆栈检查(/RTCs) /RTC1 启用快速检查(/RTCsu)
/Ge 对所有函数强制堆栈检查 /RTCc 转换为较小的类型检查
/Gs[num] 控制堆栈检查调用 /RTCs 堆栈帧运行时检查
/GS 启用安全检查 /RTCu 未初始化的本地用法检查
/clr[:noAssembly] 为公共语言运行库编译
noAssembly - 不产生程序集
/arch:SSE|SSE2 CPU 结构的最低要求,以下内容之一:
SSE - 启用支持 SSE 的 CPU 可用的指令
SSE2 - 启用支持 SSE2 的 CPU 可用的指令
-输出文件-
/Fa[file] 命名程序集列表文件 /Fofile 命名对象文件
/FA[sc] 配置程序集列表 /Fpfile 命名预编译头文件
/Fd[file] 命名 .PDB 文件 /Fr[file] 命名源浏览器文件
/Fefile 命名可执行文件 /FR[file] 命名扩展 .SBR 文件
/Fm[file] 命名映射文件
-预处理器-
/AIdir 添加到程序集搜索路径 /Fx 将插入的代码合并到文件
/FUfile 强制使用程序集/模块 /FIfile 命名强制包含文件
/C 不抽出注释 /Uname 移除预定义宏
/Dnametext 定义宏 /u 移除所有预定义宏
/E 预处理到 stdout /Idir 添加到包含搜索路径
/EP 预处理到 stdout,没有 #line /X 忽略“标准位置”
/P 预处理到文件
-语言-
/Zi 启用调试信息 /Ze 启用扩展(默认)
/ZI 启用“编辑并继续”调试信息 /Zl 省略 .OBJ 中的默认库名
/Z7 启用旧式调试信息 /Zg 生成函数原型
/Zd 仅有行号调试信息 /Zs 只进行语法检查
/Zp[n] 在 n 字节边界上包装结构 /vd 禁用/启用 vtordisp
/Za 禁用扩展(暗指 /Op) /vmx 指向成员的指针类型
/Zc:arg1[,arg2] C++ 语言一致性,这里的参数可以是:
forScope - 对范围规则强制使用标准 C++
wchar_t - wchar_t 是本机类型,不是 typedef
- 杂项 -
@file 选项响应文件 /won 发出一次警告 n
/?, /help 打印此帮助消息 /wln 为 n 设置警告等级 1-4
/c 只编译,不链接 /Wn 设置警告等级(默认 n=1)
/Hnum 最大外部名称长度 /Wall 启用所有警告
/J 默认 char 类型是 unsigned /Wp64 启用 64 位端口定位警告
/nologo 取消显示版权消息 /WX 将警告视为错误
/showIncludes 显示包含文件名 /WL 启用单行诊断
/Tcsource file 将文件编译为 .c /Yc[file] 创建 .PCH 文件
/Tpsource file 将文件编译为 .cpp /Yd 将调试信息放在每个 .OBJ 中
/TC 将所有文件编译为 .c /Yl[sym] 为调试库插入 .PCH 引用
/TP 将所有文件编译为 .cpp /Yu[file] 使用 .PCH 文件
/Vstring 设置版本字符串 /YX[file] 自动 .PCH
/w 禁用所有警告 /Y- 禁用所有 PCH 选项
/wdn 禁用警告 n /Zmn 最大内存分配(默认为 %)
/wen 将警告 n 视为错误
-链接-
/MD 与 MSVCRT.LIB 链接 /MDd 与 MSVCRTD.LIB 调试库链接
/ML 与 LIBC.LIB 链接 /MLd 与 LIBCD.LIB 调试库链接
/MT 与 LIBCMT.LIB 链接 /MTd 与 LIBCMTD.LIB 调试库链接
/LD 创建 .DLL /Fnum 设置堆栈大小
/LDd 创建 .DLL 调试库 /link [链接器选项和库]
如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!
/**------------------------------------------------------
进入程序后可以根据菜单选项进入不同的模块
1.使用首次适应算法分配空间
2.使用最佳适应算法分配空间
3.释放一块空间
4.显示内存分配情况
5.退出系统
----------------------------------------------------------**/
#include stdio.h
#include stdlib.h
#include string.h
#include conio.h
#define MEMSIZE 100 /*定义内存大小为100*/
#define MINSIZE 2 /*如果小于此值 将不再分割内存*/
typedef struct _MemoryInfomation{/* 内存空间分区表 结构*/
int start; /*起始地址*/
int size; /*大小*/
char info; /*状态 F:空闲(Free) U:占用(Used) E 结束(end)*/
}MEMINFO;
MEMINFO MemList[MEMSIZE]; //内存空间信息表
void Display();
/*--------------------------------------------------------
函数名:InitALL()
功 能:初始化所有变量
--------------------------------------------------------*/
void InitAll(){
int i;
MEMINFO temp={0,0,'e'};
for(i=0;iMEMSIZE;i++) //初始化空间信息表
MemList[i]=temp;
MemList[0].start=0; //起始地址为0
MemList[0].size=MEMSIZE;//空间初始为最大的
MemList[0].info='f'; //状态为空闲
}
/*--------------------------------------------------------
函数名:FirstFit_new()
功 能:首次适应算法分配内存
--------------------------------------------------------*/
void FirstFit_new(){
int i,j,size;
char temp[10];
printf("FirstFit_new:How many MEMORY requir?");
gets(temp);
size=atoi(temp); //将字符串转化为整数
for(i=0; i MEMSIZE-1 MemList[i].info != 'e';i++) //到了空间尾且没有空间分配
{
if(MemList[i].size = size MemList[i].info=='f') //满足所需要的大小,且是空闲空间
{
if(MemList[i].size - size = MINSIZE) //如果小于规定的最小差则将整个空间分配出去
MemList[i].info='u'; //标志为使用
else
{
for(j = MEMSIZE-2; j i; j--) //将i后的信息表元素后移
{
MemList[j+1]=MemList[j];
}
//将i分成两部分,使用低地址部分
MemList[i+1].start= MemList[i].start+size;
MemList[i+1].size = MemList[i].size-size;
MemList[i+1].info='f';
MemList[i].size=size;
MemList[i].info='u';
}
break;
}
}
if(i == MEMSIZE-1 || MemList[i].info=='e') //没有找到符合分配的空间
{
printf("Not Enough Memory!!\n");
getchar();
}
Display();
}
/*--------------------------------------------------------
函数名:BestFit_new()
功 能:最佳适应算法分配内存
--------------------------------------------------------*/
void BestFit_new()
{
int i,j,k,flag,size;
char temp[10];
printf("BestFit_new How many MEMORY requir?");
gets(temp);
size=atoi(temp); //将字符串转化为整数
j=0;
flag=0; //标志是否有合适的空间分配,0无,1有
k=MEMSIZE; //用来保存满足要求的最小空间
for(i=0;iMEMSIZE-1 MemList[i].info!='e';i++)
{
if(MemList[i].size = size MemList[i].info == 'f') //符合要求
{
flag=1;
if(MemList[i].size k) //比符合要求的最小空间小,则交换
{
k=MemList[i].size;
j=i;
}
}
}
i=j;
if(flag == 0) //没找到
{
printf("Not Enough Memory!\n");
getch();
j=i;
}
else if(MemList[i].size - size = MINSIZE) //小于规定的最小差,将整个空间分配
MemList[i].info='u';
else
{
for(j = MEMSIZE-2; j i; j--) //后移
MemList[j+1]=MemList[j];
MemList[i+1].start=MemList[i].start+size;
MemList[i+1].size=MemList[i].size-size;
MemList[i+1].info='f';
MemList[i].size=size;
MemList[i].info='u';
}
Display();
}
/*--------------------------------------------------------
最坏适应算法
*/
void BadFit_new()
{
int i,j,k,flag,size;
char temp[10];
printf("BadFit_new How many MEMORY requir?");
gets(temp);
size=atoi(temp);
j=0;
flag=0;
k=0; //保存满足要求的最大空间
for(i=0;iMEMSIZE-1MemList[i].info!='e';i++)
{
if(MemList[i].size=sizeMemList[i].info=='f')
{
flag=1;
if(MemList[i].sizek)
{
k=MemList[i].size;
j=i;
}
}
}
i=j;
if(flag=0)
{
printf("Not Enough Memory!\n");
getch();
j=i;
}
else if(MemList[i].size-size=MINSIZE)
MemList[i].info='u';
else
{
for(j=MEMSIZE-2;ji;j--)
MemList[j+1]=MemList[j];
MemList[i+1].start=MemList[i].start+size;
MemList[i+1].size=MemList[i].size-size;
MemList[i+1].info='f';
MemList[i].size=size;
MemList[i].info='u';
}
Display();
}
/*--------------------------------------------------------
函数名:del()
功 能:释放一块内存
--------------------------------------------------------*/
void del()
{
int i,number;
char temp[10];
printf("\nplease input the NUMBER you want stop:");
gets(temp);
number=atoi(temp);
if(MemList[number].info == 'u') //输入的空间是使用的
{
MemList[number].info = 'f'; //标志为空闲
if(MemList[number+1].info == 'f') //右空间为空则合并
{
MemList[number].size+=MemList[number+1].size; //大小合并
for(i=number+1;i MEMSIZE-1 MemList[i].info !='e';i++)/* i后的空间信息表元素前移 */
if(i0)
MemList[i]=MemList[i+1];
}
if(number 0 MemList[number-1].info=='f') //左空间空闲则合并
{
MemList[number-1].size+=MemList[number].size;
for(i=number;iMEMSIZE-1MemList[i].info!='e';i++)
MemList[i]=MemList[i+1];
}
}
else
{
printf("Thist Number is Not exist or is Not used!\n ");
getchar();
}
Display();
}
/*--------------------------------------------------------
函数名:Display()
功 能:显示内存状态
--------------------------------------------------------*/
void Display(){
int i,
used=0; //记录可以使用的总空间量
/* clrscr();*/
printf("\n----------------------------------------------\n");
printf("%5s%15s%15s","Number","start","size","Info");
printf("\n----------------------------------------------\n");
for(i=0;i MEMSIZE MemList[i].info != 'e';i++)
{
if(MemList[i].info == 'u')
used+=MemList[i].size;
printf("%5d%15d%15d%15s\n",i,MemList[i].start,MemList[i].size,MemList[i].info=='u'?"USED":"FREE");
}
printf("\n----------------------------------------------\n");
printf("Totalsize:%-10d Used:%-10d Free:%-10d\n",MEMSIZE,used,MEMSIZE-used);
printf("\n\n Press Any Key to return...");
getch();
}
/*--------------------------------------------------------
函数名:main()
功 能:主函数
--------------------------------------------------------*/
void main(){
char ch;
InitAll();
while(1){
printf("========================================================\n");
printf(" 1.Get a block use the FISTFIT method\n");
printf(" 2.Get a block use the BESTFIT method\n");
printf(" 3.Get a block use the BadFIT method\n");
printf(" 4.Free a block\n");
printf(" 5.Display Mem info \n");
printf(" 6.Exit \n");
printf("========================================================\n");
ch=getch();
switch(ch){
case '1':FirstFit_new();break; //首次适应算法
case '2':BestFit_new();break; //最佳适应算法
case '3':BadFit_new();break; //最坏适应算法
case '4':del();break; //删除已经使用完毕的空间
case '5':Display();break; //显示内存分配情况
case '6':exit(0);
}
}
}
取个例子,L是一条链子,刚开始L-first是链头,你反转链子的过程就是把一节链环拆下来,再接在L的头部
q=p-next就是把q拆下来,;p-next=q-next就是把被拆成两部分的链子连在一起;q-next=L-first把q接在L的头部,L-fist=q就是把L的头部改为q