#include stdio.h
成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),東臺(tái)企業(yè)網(wǎng)站建設(shè),東臺(tái)品牌網(wǎng)站建設(shè),網(wǎng)站定制,東臺(tái)網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,東臺(tái)網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
#include stdlib.h
#include time.h //用到了time函數(shù)
int main()
{ int i,number;
srand((unsigned) time(NULL)); //用時(shí)間做種,每次產(chǎn)生隨機(jī)數(shù)不一樣
for (i=0; i50; i++)
{
number = rand() % 101; //產(chǎn)生0-100的隨機(jī)數(shù)
printf("%d ", number);
}
return 0;
}
/*
5.快速排序
思路:選定一個(gè)值(可隨機(jī),可為a[0],隨機(jī)更好),將小于這個(gè)數(shù)的所有數(shù)放在它的左邊,大于這個(gè)數(shù)的放在右邊。
*/
templatetypename T
void quickSort(vectorT a, int l, int r)
{
if(lr)
{
int q=partition(a,l,r);
quickSort(a,l,q-1);
quickSort(a,q+1,r);
}
}
templatetypename T
int partition(vectorT a, int l, int r)
{
T temp=a[l],t;
int i=l,j=r+1;
while(true)
{
while( a[++i]temp i=r);
while( a[--j]temp);
if(i=j) break;
t=a[i];
a[i]=a[j];
a[j]=t;
}
a[l]=a[j];
a[j]=temp;
return j;
}
/*
5.1 快速排序--使用隨機(jī)數(shù)做基數(shù)
*/
templatetypename T
int RandPartion(vectorT a,int l, int r)
{
srand(time(0)*l*r);
int i=int(random()%(l-r)+l);
//couta.size()endl;
T temp =a[l];
a[l]=a[i];
a[i]=temp;
return partition(a,l,r);
}
templatetypename T
void RandQuicksort(vectorT a, int l, int r)
{
if(lr)
{
int m=RandPartion(a,l,r);
//cout"pre "l" " m-1" "endl;
RandQuicksort(a,l,m-1);
//cout"lat "m+1" " r" "endl;
RandQuicksort(a,m+1,r);
}
}
時(shí)間:
平均O(n 2 ) 最差O(n 2 ) 最好O(n)
空間:
O(1)
它的工作原理:首先在未排序序列中找到最?。ù螅┰?,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最?。ù螅┰?,然后放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
n個(gè)記錄的直接選擇排序可經(jīng)過n-1趟直接選擇排序得到有序結(jié)果。具體算法描述如下:
時(shí)間:
平均O(n 2 ) 最差O(n 2 ) 最好O(n 2 )
空間:
O(1)
它的工作原理是通過構(gòu)建有序序列,對(duì)于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。
一般來說,插入排序都采用in-place在數(shù)組上實(shí)現(xiàn)。具體算法描述如下:
時(shí)間:
平均O(n 2 ) 最差O(n 2 ) 最好O(n)
空間:
O(1)
快速排序的基本思想: 二分遞歸 ,通過一趟排序?qū)⒋庞涗浄指舫瑟?dú)立的兩部分,其中一部分記錄的關(guān)鍵字均比另一部分的關(guān)鍵字小,則可分別對(duì)這兩部分記錄繼續(xù)進(jìn)行排序,以達(dá)到整個(gè)序列有序。
快速排序使用分治法來把一個(gè)串(list)分為兩個(gè)子串(sub-lists)。具體算法描述如下:
我們可以通過雙指針在O(n)的時(shí)間復(fù)雜度內(nèi)獲取合適的 j
我們?cè)O(shè)立兩個(gè)指針 i 和 j,同時(shí)設(shè)置一個(gè)標(biāo)志值 arr[low],一般來說,標(biāo)志值取數(shù)組第一個(gè)元素
上述算法結(jié)束之后,j 所在的位置即為我們尋找的 j
4.3 時(shí)間空間復(fù)雜度
時(shí)間:
平均O(nlog 2 n) 最差O(n 2 ) 最好O(nlog 2 n)
空間:
O(1)
算法思想?yún)⒖甲裕?/p>
隨機(jī)選擇快速排序是一種比較常見的優(yōu)化快速排序的方法,即隨機(jī)選取一個(gè)元素作為主元,而不是像普通快速排序那樣選取第一個(gè)元素作為主元,這種情況下雖然最壞情況仍然是O(n^2),但最壞情況不再依賴于輸入數(shù)據(jù),而是由于隨機(jī)函數(shù)取值不佳。
實(shí)際上,隨機(jī)化快速排序得到理論最壞情況的可能性僅為1/(2^n)。所以隨機(jī)化快速排序可以對(duì)于絕大多輸入數(shù)據(jù)達(dá)到O(nlogn)的期望時(shí)間復(fù)雜度。
GO是編譯性語言,所以函數(shù)的順序是無關(guān)緊要的,為了方便閱讀,建議入口函數(shù) main 寫在最前面,其余函數(shù)按照功能需要進(jìn)行排列
GO的函數(shù) 不支持嵌套,重載和默認(rèn)參數(shù)
GO的函數(shù) 支持 無需聲明變量,可變長(zhǎng)度,多返回值,匿名,閉包等
GO的函數(shù)用 func 來聲明,且左大括號(hào) { 不能另起一行
一個(gè)簡(jiǎn)單的示例:
輸出為:
參數(shù):可以傳0個(gè)或多個(gè)值來供自己用
返回:通過用 return 來進(jìn)行返回
輸出為:
上面就是一個(gè)典型的多參數(shù)傳遞與多返回值
對(duì)例子的說明:
按值傳遞:是對(duì)某個(gè)變量進(jìn)行復(fù)制,不能更改原變量的值
引用傳遞:相當(dāng)于按指針傳遞,可以同時(shí)改變?cè)瓉淼闹?,并且消耗的?nèi)存會(huì)更少,只有4或8個(gè)字節(jié)的消耗
在上例中,返回值 (d int, e int, f int) { 是進(jìn)行了命名,如果不想命名可以寫成 (int,int,int){ ,返回的結(jié)果都是一樣的,但要注意:
當(dāng)返回了多個(gè)值,我們某些變量不想要,或?qū)嶋H用不到,我們可以使用 _ 來補(bǔ)位,例如上例的返回我們可以寫成 d,_,f := test(a,b,c) ,我們不想要中間的返回值,可以以這種形式來舍棄掉
在參數(shù)后面以 變量 ... type 這種形式的,我們就要以判斷出這是一個(gè)可變長(zhǎng)度的參數(shù)
輸出為:
在上例中, strs ...string 中, strs 的實(shí)際值是b,c,d,e,這就是一個(gè)最簡(jiǎn)單的傳遞可變長(zhǎng)度的參數(shù)的例子,更多一些演變的形式,都非常類似
在GO中 defer 關(guān)鍵字非常重要,相當(dāng)于面相對(duì)像中的析構(gòu)函數(shù),也就是在某個(gè)函數(shù)執(zhí)行完成后,GO會(huì)自動(dòng)這個(gè);
如果在多層循環(huán)中函數(shù)里,都定義了 defer ,那么它的執(zhí)行順序是先進(jìn)后出;
當(dāng)某個(gè)函數(shù)出現(xiàn)嚴(yán)重錯(cuò)誤時(shí), defer 也會(huì)被調(diào)用
輸出為
這是一個(gè)最簡(jiǎn)單的測(cè)試了,當(dāng)然還有更復(fù)雜的調(diào)用,比如調(diào)試程序時(shí),判斷是哪個(gè)函數(shù)出了問題,完全可以根據(jù) defer 打印出來的內(nèi)容來進(jìn)行判斷,非??焖?,這種留給你們?nèi)?shí)現(xiàn)
一個(gè)函數(shù)在函數(shù)體內(nèi)自己調(diào)用自己我們稱之為遞歸函數(shù),在做遞歸調(diào)用時(shí),經(jīng)常會(huì)將內(nèi)存給占滿,這是非常要注意的,常用的比如,快速排序就是用的遞歸調(diào)用
本篇重點(diǎn)介紹了GO函數(shù)(func)的聲明與使用,下一篇將介紹GO的結(jié)構(gòu) struct
原文:【 】
如果有解答的不對(duì)的,麻煩各位在評(píng)論寫出來~
go的調(diào)度原理是基于GMP模型,G代表一個(gè)goroutine,不限制數(shù)量;M=machine,代表一個(gè)線程,最大1萬,所有G任務(wù)還是在M上執(zhí)行;P=processor代表一個(gè)處理器,每一個(gè)允許的M都會(huì)綁定一個(gè)G,默認(rèn)與邏輯CPU數(shù)量相等(通過runtime.GOMAXPROCS(runtime.NumCPU())設(shè)置)。
go調(diào)用過程:
可以能,也可以不能。
因?yàn)間o存在不能使用==判斷類型:map、slice,如果struct包含這些類型的字段,則不能比較。
這兩種類型也不能作為map的key。
類似棧操作,后進(jìn)先出。
因?yàn)間o的return是一個(gè)非原子性操作,比如語句 return i ,實(shí)際上分兩步進(jìn)行,即將i值存入棧中作為返回值,然后執(zhí)行跳轉(zhuǎn),而defer的執(zhí)行時(shí)機(jī)正是跳轉(zhuǎn)前,所以說defer執(zhí)行時(shí)還是有機(jī)會(huì)操作返回值的。
select的case的表達(dá)式必須是一個(gè)channel類型,所有case都會(huì)被求值,求值順序自上而下,從左至右。如果多個(gè)case可以完成,則會(huì)隨機(jī)執(zhí)行一個(gè)case,如果有default分支,則執(zhí)行default分支語句。如果連default都沒有,則select語句會(huì)一直阻塞,直到至少有一個(gè)IO操作可以進(jìn)行。
break關(guān)鍵字可跳出select的執(zhí)行。
goroutine管理、信息傳遞。context的意思是上下文,在線程、協(xié)程中都有這個(gè)概念,它指的是程序單元的一個(gè)運(yùn)行狀態(tài)、現(xiàn)場(chǎng)、快照,包含。context在多個(gè)goroutine中是并發(fā)安全的。
應(yīng)用場(chǎng)景:
例子參考:
waitgroup
channel
len:切片的長(zhǎng)度,訪問時(shí)間復(fù)雜度為O(1),go的slice底層是對(duì)數(shù)組的引用。
cap:切片的容量,擴(kuò)容是以這個(gè)值為標(biāo)準(zhǔn)。默認(rèn)擴(kuò)容是2倍,當(dāng)達(dá)到1024的長(zhǎng)度后,按1.25倍。
擴(kuò)容:每次擴(kuò)容slice底層都將先分配新的容量的內(nèi)存空間,再將老的數(shù)組拷貝到新的內(nèi)存空間,因?yàn)檫@個(gè)操作不是并發(fā)安全的。所以并發(fā)進(jìn)行append操作,讀到內(nèi)存中的老數(shù)組可能為同一個(gè),最終導(dǎo)致append的數(shù)據(jù)丟失。
共享:slice的底層是對(duì)數(shù)組的引用,因此如果兩個(gè)切片引用了同一個(gè)數(shù)組片段,就會(huì)形成共享底層數(shù)組。當(dāng)sliec發(fā)生內(nèi)存的重新分配(如擴(kuò)容)時(shí),會(huì)對(duì)共享進(jìn)行隔斷。詳細(xì)見下面例子:
make([]Type,len,cap)
map的底層是hash table(hmap類型),對(duì)key值進(jìn)行了hash,并將結(jié)果的低八位用于確定key/value存在于哪個(gè)bucket(bmap類型)。再將高八位與bucket的tophash進(jìn)行依次比較,確定是否存在。出現(xiàn)hash沖撞時(shí),會(huì)通過bucket的overflow指向另一個(gè)bucket,形成一個(gè)單向鏈表。每個(gè)bucket存儲(chǔ)8個(gè)鍵值對(duì)。
如果要實(shí)現(xiàn)map的順序讀取,需要使用一個(gè)slice來存儲(chǔ)map的key并按照順序進(jìn)行排序。
利用map,如果要求并發(fā)安全,就用sync.map
要注意下set中的delete函數(shù)需要使用 delete(map) 來實(shí)現(xiàn),但是這個(gè)并不會(huì)釋放內(nèi)存,除非value也是一個(gè)子map。當(dāng)進(jìn)行多次delete后,可以使用make來重建map。
使用sync.Map來管理topic,用channel來做隊(duì)列。
參考:
多路歸并法:
pre class="vditor-reset" placeholder="" contenteditable="true" spellcheck="false"p data-block="0"(1)假設(shè)有K路a href=""數(shù)據(jù)流/a,流內(nèi)部是有序的,且流間同為升序或降序;
/pp data-block="0"(2)首先讀取每個(gè)流的第一個(gè)數(shù),如果已經(jīng)EOF,pass;
/pp data-block="0"(3)將有效的k(k可能小于K)個(gè)數(shù)比較,選出最小的那路mink,輸出,讀取mink的下一個(gè);
/pp data-block="0"(4)直到所有K路都EOF。
/p/pre
假設(shè)文件又1個(gè)G,內(nèi)存只有256M,無法將1個(gè)G的文件全部讀到內(nèi)存進(jìn)行排序。
第一步:
可以分為10段讀取,每段讀取100M的數(shù)據(jù)并排序好寫入硬盤。
假設(shè)寫入后的文件為A,B,C...10
第二步:
將A,B,C...10的第一個(gè)字符拿出來,對(duì)這10個(gè)字符進(jìn)行排序,并將結(jié)果寫入硬盤,同時(shí)記錄被寫入的字符的文件指針P。
第三步:
將剛剛排序好的9個(gè)字符再加上從指針P讀取到的P+1位數(shù)據(jù)進(jìn)行排序,并寫入硬盤。
重復(fù)二、三步驟。
go文件讀寫參考:
保證排序前兩個(gè)相等的數(shù)其在序列的前后位置順序和排序后它們兩個(gè)的前后位置順序相同的排序叫穩(wěn)定排序。
快速排序、希爾排序、堆排序、直接選擇排序不是穩(wěn)定的排序算法。
基數(shù)排序、冒泡排序、直接插入排序、折半插入排序、歸并排序是穩(wěn)定的排序算法。
參考:
head只請(qǐng)求頁面的首部。多用來判斷網(wǎng)頁是否被修改和超鏈接的有效性。
get請(qǐng)求頁面信息,并返回實(shí)例的主體。
參考:
401:未授權(quán)的訪問。
403: 拒絕訪問。
普通的http連接是客戶端連接上服務(wù)端,然后結(jié)束請(qǐng)求后,由客戶端或者服務(wù)端進(jìn)行http連接的關(guān)閉。下次再發(fā)送請(qǐng)求的時(shí)候,客戶端再發(fā)起一個(gè)連接,傳送數(shù)據(jù),關(guān)閉連接。這么個(gè)流程反復(fù)。但是一旦客戶端發(fā)送connection:keep-alive頭給服務(wù)端,且服務(wù)端也接受這個(gè)keep-alive的話,兩邊對(duì)上暗號(hào),這個(gè)連接就可以復(fù)用了,一個(gè)http處理完之后,另外一個(gè)http數(shù)據(jù)直接從這個(gè)連接走了。減少新建和斷開TCP連接的消耗。這個(gè)可以在Nginx設(shè)置,
這個(gè)keepalive_timout時(shí)間值意味著:一個(gè)http產(chǎn)生的tcp連接在傳送完最后一個(gè)響應(yīng)后,還需要hold住keepalive_timeout秒后,才開始關(guān)閉這個(gè)連接。
特別注意TCP層的keep alive和http不是一個(gè)意思。TCP的是指:tcp連接建立后,如果客戶端很長(zhǎng)一段時(shí)間不發(fā)送消息,當(dāng)連接很久沒有收到報(bào)文,tcp會(huì)主動(dòng)發(fā)送一個(gè)為空的報(bào)文(偵測(cè)包)給對(duì)方,如果對(duì)方收到了并且回復(fù)了,證明對(duì)方還在。如果對(duì)方?jīng)]有報(bào)文返回,重試多次之后則確認(rèn)連接丟失,斷開連接。
tcp的keep alive可通過
net.ipv4.tcp_keepalive_intvl = 75 // 當(dāng)探測(cè)沒有確認(rèn)時(shí),重新發(fā)送探測(cè)的頻度。缺省是75秒。
net.ipv4.tcp_keepalive_probes = 9 //在認(rèn)定連接失效之前,發(fā)送多少個(gè)TCP的keepalive探測(cè)包。缺省值是9。這個(gè)值乘以tcp_keepalive_intvl之后決定了,一個(gè)連接發(fā)送了keepalive之后可以有多少時(shí)間沒有回應(yīng)
net.ipv4.tcp_keepalive_time = 7200 //當(dāng)keepalive起用的時(shí)候,TCP發(fā)送keepalive消息的頻度。缺省是2小時(shí)。一般設(shè)置為30分鐘1800
修改:
可以
tcp是面向連接的,upd是無連接狀態(tài)的。
udp相比tcp沒有建立連接的過程,所以更快,同時(shí)也更安全,不容易被攻擊。upd沒有阻塞控制,因此出現(xiàn)網(wǎng)絡(luò)阻塞不會(huì)使源主機(jī)的發(fā)送效率降低。upd支持一對(duì)多,多對(duì)多等,tcp是點(diǎn)對(duì)點(diǎn)傳輸。tcp首部開銷20字節(jié),udp8字節(jié)。
udp使用場(chǎng)景:視頻通話、im聊天等。
time-wait表示客戶端等待服務(wù)端返回關(guān)閉信息的狀態(tài),closed_wait表示服務(wù)端得知客戶端想要關(guān)閉連接,進(jìn)入半關(guān)閉狀態(tài)并返回一段TCP報(bào)文。
time-wait作用:
解決辦法:
close_wait:
被動(dòng)關(guān)閉,通常是由于客戶端忘記關(guān)閉tcp連接導(dǎo)致。
根據(jù)業(yè)務(wù)來啊~
重要指標(biāo)是cardinality(不重復(fù)數(shù)量),這個(gè)數(shù)量/總行數(shù)如果過小(趨近于0)代表索引基本沒意義,比如sex性別這種。
另外查詢不要使用select *,根據(jù)select的條件+where條件做組合索引,盡量實(shí)現(xiàn)覆蓋索引,避免回表。
僵尸進(jìn)程:
即子進(jìn)程先于父進(jìn)程退出后,子進(jìn)程的PCB需要其父進(jìn)程釋放,但是父進(jìn)程并沒有釋放子進(jìn)程的PCB,這樣的子進(jìn)程就稱為僵尸進(jìn)程,僵尸進(jìn)程實(shí)際上是一個(gè)已經(jīng)死掉的進(jìn)程。
孤兒進(jìn)程:
一個(gè)父進(jìn)程退出,而它的一個(gè)或多個(gè)子進(jìn)程還在運(yùn)行,那么那些子進(jìn)程將成為孤兒進(jìn)程。孤兒進(jìn)程將被init進(jìn)程(進(jìn)程號(hào)為1)所收養(yǎng),并由init進(jìn)程對(duì)它們完成狀態(tài)收集工作。
子進(jìn)程死亡需要父進(jìn)程來處理,那么意味著正常的進(jìn)程應(yīng)該是子進(jìn)程先于父進(jìn)程死亡。當(dāng)父進(jìn)程先于子進(jìn)程死亡時(shí),子進(jìn)程死亡時(shí)沒父進(jìn)程處理,這個(gè)死亡的子進(jìn)程就是孤兒進(jìn)程。
但孤兒進(jìn)程與僵尸進(jìn)程不同的是,由于父進(jìn)程已經(jīng)死亡,系統(tǒng)會(huì)幫助父進(jìn)程回收處理孤兒進(jìn)程。所以孤兒進(jìn)程實(shí)際上是不占用資源的,因?yàn)樗K究是被系統(tǒng)回收了。不會(huì)像僵尸進(jìn)程那樣占用ID,損害運(yùn)行系統(tǒng)。
原文鏈接:
產(chǎn)生死鎖的四個(gè)必要條件:
(1) 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。
(2) 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。
(3) 不剝奪條件:進(jìn)程已獲得的資源,在末使用完之前,不能強(qiáng)行剝奪。
(4) 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
避免方法:
端口占用:lsof -i:端口號(hào) 或者 nestat
cpu、內(nèi)存占用:top
發(fā)送信號(hào):kill -l 列出所有信號(hào),然后用 kill [信號(hào)變化] [進(jìn)程號(hào)]來執(zhí)行。如kill -9 453。強(qiáng)制殺死453進(jìn)程
git log:查看提交記錄
git diff :查看變更記錄
git merge:目標(biāo)分支改變,而源分支保持原樣。優(yōu)點(diǎn):保留提交歷史,保留分支結(jié)構(gòu)。但會(huì)有大量的merge記錄
git rebase:將修改拼接到最新,復(fù)雜的記錄變得優(yōu)雅,單個(gè)操作變得(revert)很簡(jiǎn)單;缺點(diǎn):
git revert:反做指定版本,會(huì)新生成一個(gè)版本
git reset:重置到某個(gè)版本,中間版本全部丟失
etcd、Consul
pprof
節(jié)省空間(非葉子節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),相對(duì)b tree的優(yōu)勢(shì)),減少I/O次數(shù)(節(jié)省的空間全部存指針地址,讓樹變的矮胖),范圍查找方便(相對(duì)hash的優(yōu)勢(shì))。
explain
其他的見:
runtime2.go 中關(guān)于 p 的定義: 其中 runnext 指針決定了下一個(gè)要運(yùn)行的 g,根據(jù)英文的注釋大致意思是說:
所以當(dāng)設(shè)置 runtime.GOMAXPROCS(1) 時(shí),此時(shí)只有一個(gè) P,創(chuàng)建的 g 依次加入 P, 當(dāng)最后一個(gè)即 i==9 時(shí),加入的最后 一個(gè) g 將會(huì)繼承當(dāng)前主 goroutinue 的剩余時(shí)間片繼續(xù)執(zhí)行,所以會(huì)先輸出 9, 之后再依次執(zhí)行 P 隊(duì)列中其它的 g。
方法一:
方法二:
[圖片上傳失敗...(image-4ef445-1594976286098)]
方法1:to_days,返回給的日期從0開始算的天數(shù)。
方法2:data_add。向日期添加指定時(shí)間間隔
[圖片上傳失敗...(image-b67b10-1594976286098)]