數(shù)據(jù)結(jié)構(gòu)中initlist是什么意思 C語言這種結(jié)構(gòu)體如何構(gòu)造一個(gè)空的線性表L?
C語言這種結(jié)構(gòu)體如何構(gòu)造一個(gè)空的線性表L?函數(shù)main()中的語句鏈表L自動(dòng)給變量L分配內(nèi)存,l對應(yīng)第二個(gè)結(jié)構(gòu),是LinkList。調(diào)用初始化函數(shù)InitList()將值賦給變量l中的成員h:初始化后
C語言這種結(jié)構(gòu)體如何構(gòu)造一個(gè)空的線性表L?
函數(shù)main()中的語句鏈表L自動(dòng)給變量L分配內(nèi)存,
l對應(yīng)第二個(gè)結(jié)構(gòu),是LinkList。
調(diào)用初始化函數(shù)InitList()將值賦給變量l中的成員h:
初始化后,鏈表長度為0。
插入數(shù)據(jù)后,鏈表長度為3。
鏈表中的數(shù)據(jù)是: 102030。
//使用代碼
整數(shù)的計(jì)算方法?
首先我們定義一個(gè)整數(shù)的平方根從非負(fù)整數(shù)映射到非負(fù)整數(shù)的函數(shù):我們可以用乘法線性搜索或者二分法搜索得到平方不超過的最大根。通過平方數(shù)的數(shù)列,我們在線性搜索中只能使用加法,因?yàn)閮蓚€(gè)完全平方數(shù)之差是一個(gè)奇數(shù)列:uint 32 _ t is qrt 0(uint 32 _ t n){ uint 32 _ t delta 3;for(uint 32 _ t square 1;平方n;△2)方三角;返回delta/2-1;}因?yàn)閱栴}是關(guān)于大整數(shù)的,所以我們要把大整數(shù)的位數(shù)()考慮進(jìn)去。線性搜索需要多次迭代,每次迭代的加法都需要時(shí)間。然而,最壞情況下的二分搜索法需要多次迭代,并且每次乘法都需要時(shí)間。但有些數(shù)值方法(如牛頓迭代)只適合計(jì)算近似,還涉及除法。讓 咱們換個(gè)思路,參考文章整數(shù)平方根。平方根的計(jì)算方法類似于長除法。在二進(jìn)制中,只需要比較和減法。32位無符號整數(shù)的C實(shí)現(xiàn)如下:uint 32 _ t is qrt 1(uint 32 _ t n){ uint 32 _ t余數(shù)0,根0,除數(shù);for(size _ t I 0;i 16i ) {根1;余數(shù)2;余數(shù)| n 30N2;//從提取2 MSBn除數(shù)(根1)1;if(除數(shù)余數(shù)){余數(shù)-除數(shù);根;} }返回root這種方法的迭代次數(shù)是次(一個(gè)整數(shù)有多少位),每次迭代的加、減、移位、比較都是一樣的??倳r(shí)間和時(shí)間復(fù)雜度低于線性和二分搜索法。由于除數(shù)和根的關(guān)系是固定的,如果空間是一個(gè)考慮因素(考慮大整數(shù)或硬件實(shí)現(xiàn)),可以把這種形式改為節(jié)省除數(shù)的存儲:uint 32 _ t is qrt 2(uint 32 _ t n){ uint 32 _ t remainder 0,root 0;for(size _ t I 0;i 16i ) {根1;根;余數(shù)2;余數(shù)| n 30N2;//從n if(根余數(shù)){余數(shù)-根)中提取2 MSB根;} else-root;}返回根1;}接下來我們用C 11泛形式寫這個(gè)算法,接受任何無符號整數(shù)類型:Template TypeName T T I SQRT(Const T N){ T Remainer { },root { };auto bit count is qrt _ traits t::bitcount(n);for(size _ t I bit count;I 0;){ I-2;根1;根;余數(shù)2;余數(shù)| isqrt _ traits t::extractwobitsat(n,I);if(根余數(shù)){ remainder-root;根;} else-root;}返回根1;} T需要支持、、前綴、前綴-、| uint8_t,還需要提供一個(gè)isqrt_traitsT來提取兩個(gè)額外的操作。對于內(nèi)置的無符號整數(shù)類型,其一般為iSqrt _ traitst如下:Template TypeName T Struct is qrt _ traitst { STatic _ ass::is _ unsign:: value,泛型isqrt只對無符號類型);//兩個(gè)靜態(tài)大小的倍數(shù)的位數(shù)_ T bit count(const T n){ T a(n);size _ t count 0;while(a 0){ a 2;計(jì)數(shù)2;}返回計(jì)數(shù);} //提取i 1,I位靜態(tài)uint 8 _ T extractwobitsat(const T n,size _ T I){ return static _ castuint 8 _ T((n I)3);} };在isqrt2的每次迭代中,我們通過移位得到兩個(gè)比特,而在isqrt中,我們使用extractwobitsat(n,I)得到第1個(gè)和第1個(gè)比特。這個(gè)變化是因?yàn)榭梢灾苯訌囊粋€(gè)大整數(shù)中獲取一個(gè)比特,而不需要復(fù)制另一個(gè)大整數(shù)進(jìn)行移位運(yùn)算。這里的BitCount()其實(shí)可以簡單的返回siz: : Vector U中,這里U一般可以設(shè)置為uint32_t或者uint64_t,并添加十六進(jìn)制流輸出:template typename U class biguint {public: biguint(): v { 0 } { } biguint(std: : initializ: v(init){ } biguint運(yùn)算符(siz: v){ U outBits x(unitBitCount-shift);x(x shift)| in bits;inBits outBits} if(in bits)v . push _ back(in bits);返回* this} biguint運(yùn)算符(size _ t shift){ assert(shift unitBitCount);u in bits 0;for(auto itr v . r begin();itr!();itr){ U outBits * itr(unitBitCount-shift);* itr(* itr shift)| in bits;inBits outBits} if(()0)v . pop _ back();返回* this} biguint運(yùn)算符|(uint 8 _ t RHS){ v[0]| RHS;返回* this} biguint運(yùn)算符-(const biguint RHS){ ass: 0;u以前的v[I];v[I]-r in borrow;inBorrow v[i]上一頁1 : 0;} assert(in borrow 0);while(()1()0)v . pop _ back();返回* this} biguint運(yùn)算符(){ for(auto x : v)if(x!0)返回* this五. push _ back(1);返回* this} biguint運(yùn)算符- () { ass: v)if(x-!0)返回* this返回* this} bool運(yùn)算符(const biguint RHS)const { if(()()){ for(auto I();異- 0;)if (v[i] rhs.v[i])返回tru:e CHO 25-@ . com:e CHO 27-@ . come stream OS,const biguint x){ auto f(OS . flags());OS 0x std:: hex;for(auto itr x . v . r begin();itr!();itr)OS * itr;OS . flags(f);返回OS;} friend struct is qrt _ traitsbiguint;privat:靜態(tài)常量size _ t unitBitCount siz:: vectoru v;};并為biguintU提供一個(gè)iSqrt _ Traits:Template TypeName ustrct iSqrt _ Traitsbiguintu { static size _ t bit count(const biguintU n)。{ r::itbitcount *(()-1)is qrt _ traitsu::bitcount(());} static uint 8 _ t extractwobitsat(const biguintU n,size _ t I){ return static _ castuint 8 _ t((n . v[I/biguintu: unit: unitbitcount](I biguintu: unit: unitbitcount))3);} };我簡單測了一下45765和50!開平party:int main(){//floor(SQRT(45765))213 STD : : Cout I SQRT 1(45765)STD : : : : cout isqrt 2(45765)std: : : : cout isqrtunsign: : endl;// 50!49 eebc 961 ed 279 b 02 B1 ef 4f 28d 19 a 84 f 5973 a1d 2c 7800000000000//樓層(sqrt(50!))899310 e 94 A8 b 185249821 ebc: : cout is qrt(biguintuit 32 _ t { 0x 00000000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x 49 eebc })std: echo 56--} output $ g-stdc 11-o isqrt isqrt . CPP ./isqrt 213 213 213 0x 899310 e 94 A8 b 185249821 ebce 7050!平方根(sqrt(50!))在十六進(jìn)制匹配(知乎插入的網(wǎng)址有bug)。原代碼在大整數(shù)平方根github。注意:還沒有完全測試過。-更新1:按@計(jì)算提示大海無邊,時(shí)間復(fù)雜度的順序應(yīng)該是-更新2: I sqrt 0()之前有錯(cuò)誤,感謝@LOOP反饋。