C语言这种结构体如何构造一个空的线性表L?
函数main()中的语句链表L自动给变量L分配内存,
l对应第二个结构,是linkList。
调用初始化函数InitList()将值赋给变量l中的成员h:
初始化后,链表长度为0。
插入数据后,链表长度为3。
链表中的数据是:102030。
//使用代码
整数的计算方法?
首先我们定义一个整数的平方根从非负整数映射到非负整数的函数:我们可以用乘法线性搜索或者二分法搜索得到平方不超过的最大根。通过平方数的数列,我们在线性搜索中只能使用加法,因为两个完全平方数之差是一个奇数列:uint32_tisqrt0(uint32_tn){uint32_tdelta3;for(uint32_tsquare1;平方n;△2)方三角;返回delta/2-1;}因为问题是关于大整数的,所以我们要把大整数的位数()考虑进去。线性搜索需要多次迭代,每次迭代的加法都需要时间。然而,最坏情况下的二分搜索法需要多次迭代,并且每次乘法都需要时间。但有些数值方法(如牛顿迭代)只适合计算近似,还涉及除法。让咱们换个思路,参考文章整数平方根。平方根的计算方法类似于长除法。在二进制中,只需要比较和减法。32位无符号整数的C实现如下:uint32_tisqrt1(uint32_tn){uint32_t余数0,根0,除数;for(size_tI0;i16i){根1;余数2;余数|n30N2;//从提取2MSBn除数(根1)1;if(除数余数){余数-除数;根;}}返回root这种方法的迭代次数是次(一个整数有多少位),每次迭代的加、减、移位、比较都是一样的。总时间和时间复杂度低于线性和二分搜索法。由于除数和根的关系是固定的,如果空间是一个考虑因素(考虑大整数或硬件实现),可以把这种形式改为节省除数的存储:uint32_tisqrt2(uint32_tn){uint32_tremainder0,root0;for(size_tI0;i16i){根1;根;余数2;余数|n30N2;//从nif(根余数){余数-根)中提取2MSB根;}else-root;}返回根1;}接下来我们用C11泛形式写这个算法,接受任何无符号整数类型:TemplateTypeNameTTISQRT(ConstTN){TRemainer{},root{};autobitcountisqrt_traitst::bitcount(n);for(size_tIbitcount;I0;){I-2;根1;根;余数2;余数|isqrt_traitst::extractwobitsat(n,I);if(根余数){remainder-root;根;}else-root;}返回根1;}T需要支持、、前缀、前缀-、|uint8_t,还需要提供一个isqrt_traitsT来提取两个额外的操作。对于内置的无符号整数类型,其一般为iSqrt_traitst如下:TemplateTypeNameTStructisqrt_traitst{STatic_ass::is_unsign::value,泛型isqrt只对无符号类型);//两个静态大小的倍数的位数_Tbitcount(constTn){Ta(n);size_tcount0;while(a0){a2;计数2;}返回计数;}//提取i1,I位静态uint8_Textractwobitsat(constTn,size_TI){returnstatic_castuint8_T((nI)3);}};在isqrt2的每次迭代中,我们通过移位得到两个比特,而在isqrt中,我们使用extractwobitsat(n,I)得到第1个和第1个比特。这个变化是因为可以直接从一个大整数中获取一个比特,而不需要复制另一个大整数进行移位运算。这里的BitCount()其实可以简单的返回siz::VectorU中,这里U一般可以设置为uint32_t或者uint64_t,并添加十六进制流输出:templatetypenameUclassbiguint{public:biguint():v{0}{}biguint(std::initializ:v(init){}biguint运算符(siz:v){UoutBitsx(unitBitCount-shift);x(xshift)|inbits;inBitsoutBits}if(inbits)v.push_back(inbits);返回*this}biguint运算符(size_tshift){assert(shiftunitBitCount);uinbits0;for(autoitrv.rbegin();itr!();itr){UoutBits*itr(unitBitCount-shift);*itr(*itrshift)|inbits;inBitsoutBits}if(()0)v.pop_back();返回*this}biguint运算符|(uint8_tRHS){v[0]|RHS;返回*this}biguint运算符-(constbiguintRHS){ass:0;u以前的v[I];v[I]-rinborrow;inBorrowv[i]上一页1:0;}assert(inborrow0);while(()1()0)v.pop_back();返回*this}biguint运算符(){for(autox:v)if(x!0)返回*this五.push_back(1);返回*this}biguint运算符-(){ass:v)if(x-!0)返回*this返回*this}bool运算符(constbiguintRHS)const{if(()()){for(autoI();异-0;)if(v[i]rhs.v[i])返回tru:eCHO25-@.com:eCHO27-@.comestreamOS,constbiguintx){autof(OS.flags());OS0xstd::hex;for(autoitrx.v.rbegin();itr!();itr)OS*itr;OS.flags(f);返回OS;}friendstructisqrt_traitsbiguint;privat:静态常量size_tunitBitCountsiz::vectoruv;};并为biguintU提供一个iSqrt_Traits:TemplateTypeNameustrctiSqrt_Traitsbiguintu{staticsize_tbitcount(constbiguintUn)。{r::itbitcount*(()-1)isqrt_traitsu::bitcount(());}staticuint8_textractwobitsat(constbiguintUn,size_tI){returnstatic_castuint8_t((n.v[I/biguintu:unit:unitbitcount](Ibiguintu:unit:unitbitcount))3);}};我简单测了一下45765和50!开平party:intmain(){//floor(SQRT(45765))213STD::CoutISQRT1(45765)STD::::coutisqrt2(45765)std::::coutisqrtunsign::endl;//50!49eebc961ed279b02B1ef4f28d19a84f5973a1d2c7800000000000//楼层(sqrt(50!))899310e94A8b185249821ebc::coutisqrt(biguintuit32_t{0x00000000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc})std:echo56--}output$g-stdc11-oisqrtisqrt.CPP./isqrt2132132130x899310e94A8b185249821ebce7050!平方根(sqrt(50!))在十六进制匹配(知乎插入的网址有bug)。原代码在大整数平方根github。注意:还没有完全测试过。-更新1:按@计算提示大海无边,时间复杂度的顺序应该是-更新2:Isqrt0()之前有错误,感谢@LOOP反馈。