當前位置:首頁 » 文件管理 » c緩存機制

c緩存機制

發布時間: 2022-11-04 10:51:44

A. 前端瀏覽器緩存機制

在前端開發中,性能是一個永恆的話題,沒有最好,只有更好。判斷一個網站性能好壞,一個直入眼觀的即是網頁的反應速度,有一個方式就是使用緩存,一個優秀的緩存策略可以縮短網頁請求的時間,減少延遲,並且網頁可以重復利用,還可以減少帶寬,降低網路負荷。

1: 為什麼需要緩存?

a:緩存可以減少用戶等待時間,提升用戶體驗

b:減少網路帶寬消耗

c:降低伺服器壓力

Note:緩存使用不當,也會造成『臟數據』問題

2:常見的緩存類型

強緩存 -

Expires伺服器端設置,表示該資源的過期時間,會有弊端,客戶端時間和伺服器時間不一致的問題。

Cache-Control:max-age表示緩存資源的最大生命周期,單位是秒

所以Expires 結合 Cache-Control 一起使用,大型網站中一般比較適用

協商緩存-

Last-Modified:值為資源的最後更新時間,隨伺服器response返回

If-Modified-Since:通過比較兩個時間來判斷資源在兩次請求期間是否有過修改,如果沒有,則命中協商緩存

Etag:表示資源內容的唯一標識,即資源的消息摘要

If-None-Match:伺服器通過比較請求頭中的If-None-Match與當前資源的Etag是否一致來判斷資源是否在兩次請求期間有過修改

3:緩存流程圖示:

a:瀏覽器會先檢測強緩存類型(Cache-Control 或者 Expires)是否有效;命中直接瀏覽器本地獲取緩存資源

b:未命中。伺服器會根據請求頭Request Header驗證這個資源是否命中協商緩存,稱之為HTTP二次驗證,命中,伺服器返回請求,但返回資源,而是告訴客戶端直接中直接從瀏覽器緩存中獲取

Note:

1.強緩存不會發生請求,協商緩存存在伺服器請求

2.當協商緩存也未命中時,則伺服器會將資源發送到客戶端

3.F5刷新頁面,會跳過強緩存

4.Ctrl+F5刷新頁面,跳過強緩存和協商緩存

5.不會緩存的情況

HTTPS POST請求 根據Cookie獲取認證信息 Request Header Cache-Control:no-cache, max-age=0

6.小故事大道理

上文對整個概念做了闡述,還是不夠形象,我們來通過幾個小故事生動理解一下:

故事一:Last-Modified

瀏覽器:Hi,我需要 jartto.min.js 這個文件,如果是在 Last-Modified: Fri Feb 15 2019 19:57:31 GMT 之後修改過的,請發給我。

伺服器:(檢查文件的修改時間)

伺服器:Oh,這個文件在那個時間之後沒有被修改過,你已經有最新的版本了。

瀏覽器:太好了,那我就顯示給用戶了。

故事二:ETag

瀏覽器:Hi,我需要 jartto.css 這個文件,有沒有不匹配 3c61f-1c1-2aecb436 這個串的

伺服器:(檢查 ETag…)

伺服器:Hey,我這里的版本也是 3c61f-1c1-2aecb436,你已經是最新的版本了

瀏覽器:好,那就可以使用本地緩存了

B. 瀏覽器的渲染過程及涉及到的緩存機制

答:dns解析-》tcp鏈接-》發送HTTP請求-》伺服器處理請求並且返回報文-》瀏覽器解析渲染頁面-》鏈接結束

是一個將網址解析成IP 地址的過程。
首先從本地域名伺服器中查找,如果找不到就繼續向上根域名伺服器查找,直到頂級域名,這個過程中存在dns優化有的環節。當查找資源時, 會先找緩存,(瀏覽器緩存-》系統緩存-》路由器緩存等等),也會根據機器的負載量和距離用戶的位置進行dns負載均衡。

A.客戶端發送syn到伺服器要求連接
B.服務端向客戶端發送ack
C.客戶端收到ack並確認後,向服務端發送ack,連連接建立。

tcp連接建立之後,開始通過HTTP協議傳輸資源,根據情況判斷是否使用HTTPS,HTTP包括請求行,請求報頭,請求正文(post,put客戶端向伺服器傳輸數據的情況)。keepalive什麼的可以在請求頭里添加。

(此處涉及強制緩存和協商緩存, 為了先講清楚瀏覽器渲染過程,我把他們放在文章末尾。)

服務端接到請求開始對tcp進行處理,對http進行解析,按照報文格式封裝成HTTP request對象。響應報文碼(1xx:請求已接受,2XX:成功,3xx:重定向,4xx:客戶端錯誤,5xx:服務端錯誤)

邊解析邊渲染,首先解析html,構建dom樹,然後解析css,構建cssom。

我思考過很久HTML和css誰先渲染。我的理解是,不一定,看位置了,如果dom構建的過程中遇到了css的link,那就會先去載入並構建cssom,這個過程不是一次性的。 css和同步的js文件都是阻塞DOM樹渲染的,但不阻塞DOM解析, 直到js載入並且執行完畢。遇到阻塞的css也會延遲js的執行和dom構建。(因為js可能會修改dom或者cssom),css同樣,當cssom構建時,js也會停止被阻塞,等待cssom構建完成。

defer & async
1.正常模式
<script src="script.js"></script>
遇到這樣的js標簽,瀏覽器會立即載入並執行,不等待後續載入的文檔元素。

2.async模式
<script async src="script.js"></script>
有async的js文件會和後續的DOM解析渲染並行執行,當js載入完成,立即執行,這時html解析暫停。因此不會按照標簽引入順序執行。

3.defer模式
<script defer src="script.js"></script>
有defer的js文件的載入,也會和文檔的解析構建並行。這一點與async一致。
不同的是,defer的js文件載入完不會立即執行, 會等到所有文檔解析完成後,DOMContentLoaded事件觸發之前完成, 因此會按照引入順序執行。

DOMContentLoaded & onload
DOM解析完(阻塞DOM的內容解析完,DOM才真正解析完)會觸發DOMContentLoaded事件。如果在DOMContentLoaded之後引入css樣式表,DOMContentLoaded可能無法獲取樣式表裡的樣式,此時DOM樹已經構建完成,但外部css文件還沒載入完成,這也是 css文件放在頭部的原因

onLoad
頁面的所有資源被載入以後觸發onLoad事件,會在DOMContentLoaded之後觸發。

這個過程中有兩個重要的過成是迴流和重繪。計算盒模型的大小位置還有解析顏色字體等 屬性,這些都確定下來的時候開始repain,合成一個rendertree渲染樹,render-tree中必須同時存在dom和cssom,瀏覽器開始布局並渲染到屏幕上。首次載入必然會經歷迴流和重繪的過程。

無論何時總會有一個初始化的頁面布局伴隨著一次繪制。(除非你希望你的頁面是空白的:))之後,每一次改變用於構建渲染樹的信息都會導致以下至少一個的行為:

部分渲染樹(或者整個渲染樹)需要重新分析並且節點尺寸需要重新計算。這被稱為重排。注意這里至少會有一次重排-初始化頁面布局。

由於節點的幾何屬性發生改變或者由於樣式發生改變,例如改變元素背景色時,屏幕上的部分內容需要更新。這樣的更新被稱為重繪。

重排和重繪代價是高昂的,它們會破壞用戶體驗,並且讓UI展示非常遲緩。

一些重排可能開銷更大。想像一下渲染樹,如果你直接改變body下的一個子節點,可能並不會對其它節點造成影響。但是當你給一個當前頁面頂級的div添加動畫或者改變它的大小,就會推動整個頁面改變-聽起來代價就十分高昂。

瀏覽器一直致力於減少這些消極的影響,瀏覽器會創建一個變化的隊列,瀏覽器可以向隊列添加或變更這些變化,在一個特定的時間或達到一定的數量時,執行一次重排或重繪,通過這種方式,多次重排或重繪會整合起來最終減少重排或重繪的次數,以節省瀏覽器渲染的開銷。

所以 ,同時set和get樣式是非常糟糕的做法

看到的一個答案,有可能是這個原因,但是我不確定。
開發環境會把css都打包到js里,所以要等js載入好了才有樣式,因此會出現這種情況;但是在生產環境下,css會生成css文件,並插入到<style />里,因此就不會出現這種情況了。

兩個優化點:css先載入,js後載入
js盡量不要修改dom樹。

以下是我在OneNote的筆記,粘貼過來就會變成圖片沒有找到好的辦法。
強制緩存和協商緩存是http請求這一步的內容。

C. Cache的的工作原理是什麼

CACHE 快取

CACHE是一種加速內存或磁碟存取的裝置,可將慢速磁碟上的數據拷貝至快速的磁碟進行讀寫動作,以提升系統響應的速度。

其運作原理在於使用較快速的儲存裝置保留一份從慢速儲存裝置中所讀取數據且進行拷貝,當有需要再從較慢的儲存體中讀寫數據時,CACHE能夠使得讀寫的動作先在快速的裝置上完成,如此會使系統的響應較為快速。

舉例來說,存取內存 (RAM) 的速度較磁碟驅動器快非常多,所以我們可以將一部份的主存儲器保留當成磁碟CACHE,每當有磁碟讀取的需求時就把剛讀取的數據拷貝一份放在CACHE內存中,如果系統繼續要求讀取或寫入同一份數據或同一扇區 (sector) 時,系統可以直接從內存中的CACHE部分作讀寫的動作,這樣系統對磁碟的存取速度感覺上會快許多。

同樣的,靜態內存 (SRAM) 比動態內存 (DRAM) 的讀寫速度快,使用些靜態內存作為動態內存的CACHE,也可以提升讀寫的效率。

內存不全部使用SRAM取代DRAM 的原因,是因為SRAM的成本較DRAM高出許多。

使用CACHE的問題是寫入CACHE中的數據如果不立即寫回真正的儲存體,一但電源中斷或其它意外會導致數據流失;但若因而每次都將數據寫寫回真正的儲存體,又將會使得CACHE只能發揮加速讀取的功能,而不能加速寫入的速度,這樣的狀況使得CACHE寫入的方式分為兩類:

1. Write-Through: 每次遇到寫入時就將數據寫入真正的儲存體。

2. Write-Back: 遇到寫入時不一定回寫,只紀錄在CACHE內,並將該份數據標示為已更改(dirty),等系統有空或等到一定的時間後再將數據寫回真正的儲存體,這種做法是承擔一點風險來換取效率。

由於很多時候系統不只有重復讀寫同一塊區域,使用兩組各自獨立的CACHE效能通常比只使用一組較佳,這稱為 2-Ways Associate,同樣的,使用四組CACHE則稱為4ways Associate,但更多組的CACHE會使得演算法相對的復雜許多。

CACHE的效能依演算法的使用而有好壞之分,估量的單位通常使用命中率 (hits),命中率較高者較佳。

新式的CPU上也有內建的CACHE,稱為 LEVEL 1 (L1) 快取, 由於與 CPU 同頻率運作,能比在主機板上的 LEVEL 2 (L2) CACHE提供更快速的存取效能。

D. c語言的輸入緩沖怎麼回事,哪裡有詳細介紹啊

緩沖是標准C中的標准I/O里的機制,標准庫里的I/O語句為了提高讀寫的效率,在實際讀寫之前將數據保存到一段內存中,這段內存就叫緩沖,分全緩沖,行緩沖兩種,全緩沖在緩沖的內存滿了之後做實際的讀寫,行緩沖在遇到換行符之後做實際的讀寫,unix高級環境編程里第五章里有詳細的說明,或者網路也有

E. 什麼叫二級緩存

CPU緩存(Cache Memory)位於CPU與內存之間的臨時存儲器,它的容量比內存小但交換速度快。在緩存中的數據是內存中的一小部分,但這一小部分是短時間內CPU即將訪問的,當CPU調用大量數據時,就可避開內存直接從緩存中調用,從而加快讀取速度。由此可見,在CPU中加入緩存是一種高效的解決方案,這樣整個內存儲器(緩存+內存)就變成了既有緩存的高速度,又有內存的大容量的存儲系統了。緩存對CPU的性能影響很大,主要是因為CPU的數據交換順序和CPU與緩存間的帶寬引起的。

緩存的工作原理是當CPU要讀取一個數據時,首先從緩存中查找,如果找到就立即讀取並送給CPU處理;如果沒有找到,就用相對慢的速度從內存中讀取並送給CPU處理,同時把這個數據所在的數據塊調入緩存中,可以使得以後對整塊數據的讀取都從緩存中進行,不必再調用內存。

正是這樣的讀取機制使CPU讀取緩存的命中率非常高(大多數CPU可達90%左右),也就是說CPU下一次要讀取的數據90%都在緩存中,只有大約10%需要從內存讀取。這大大節省了CPU直接讀取內存的時間,也使CPU讀取數據時基本無需等待。總的來說,CPU讀取數據的順序是先緩存後內存。

最早先的CPU緩存是個整體的,而且容量很低,英特爾公司從Pentium時代開始把緩存進行了分類。當時集成在CPU內核中的緩存已不足以滿足CPU的需求,而製造工藝上的限制又不能大幅度提高緩存的容量。因此出現了集成在與CPU同一塊電路板上或主板上的緩存,此時就把 CPU內核集成的緩存稱為一級緩存,而外部的稱為二級緩存。一級緩存中還分數據緩存(Data Cache,D-Cache)和指令緩存(Instruction Cache,I-Cache)。二者分別用來存放數據和執行這些數據的指令,而且兩者可以同時被CPU訪問,減少了爭用Cache所造成的沖突,提高了處理器效能。英特爾公司在推出Pentium 4處理器時,用新增的一種一級追蹤緩存替代指令緩存,容量為12KμOps,表示能存儲12K條微指令。

隨著CPU製造工藝的發展,二級緩存也能輕易的集成在CPU內核中,容量也在逐年提升。現在再用集成在CPU內部與否來定義一、二級緩存,已不確切。而且隨著二級緩存被集成入CPU內核中,以往二級緩存與CPU大差距分頻的情況也被改變,此時其以相同於主頻的速度工作,可以為CPU提供更高的傳輸速度。

二級緩存是CPU性能表現的關鍵之一,在CPU核心不變化的情況下,增加二級緩存容量能使性能大幅度提高。而同一核心的CPU高低端之分往往也是在二級緩存上有差異,由此可見二級緩存對於CPU的重要性。

CPU在緩存中找到有用的數據被稱為命中,當緩存中沒有CPU所需的數據時(這時稱為未命中),CPU才訪問內存。從理論上講,在一顆擁有二級緩存的CPU中,讀取一級緩存的命中率為80%。也就是說CPU一級緩存中找到的有用數據占數據總量的80%,剩下的20%從二級緩存中讀取。由於不能准確預測將要執行的數據,讀取二級緩存的命中率也在80%左右(從二級緩存讀到有用的數據占總數據的16%)。那麼還有的數據就不得不從內存調用,但這已經是一個相當小的比例了。目前的較高端的CPU中,還會帶有三級緩存,它是為讀取二級緩存後未命中的數據設計的—種緩存,在擁有三級緩存的CPU中,只有約5%的數據需要從內存中調用,這進一步提高了CPU的效率。

為了保證CPU訪問時有較高的命中率,緩存中的內容應該按一定的演算法替換。一種較常用的演算法是「最近最少使用演算法」(LRU演算法),它是將最近一段時間內最少被訪問過的行淘汰出局。因此需要為每行設置一個計數器,LRU演算法是把命中行的計數器清零,其他各行計數器加1。當需要替換時淘汰行計數器計數值最大的數據行出局。這是一種高效、科學的演算法,其計數器清零過程可以把一些頻繁調用後再不需要的數據淘汰出緩存,提高緩存的利用率。

CPU產品中,一級緩存的容量基本在4KB到64KB之間,二級緩存的容量則分為128KB、256KB、512KB、1MB、2MB等。一級緩存容量各產品之間相差不大,而二級緩存容量則是提高CPU性能的關鍵。二級緩存容量的提升是由CPU製造工藝所決定的,容量增大必然導致CPU內部晶體管數的增加,要在有限的CPU面積上集成更大的緩存,對製造工藝的要求也就越高

F. C語言求助……

好像沒有吧
ret=scanf("%d,%d",&a,&b)
這句編譯系統當做邏輯表達式
只要輸入的是int型的ret的值都為1
即真,否則別的類型假,ret的值只能為0或1
所以這句while(ret!=2)好像沒什麼意義吧,

G. c語言getchar()能接受多個字元

getchar函數每次只從緩沖區中接受一個字元。


getchar有一個int型的返回值。

當程序調用getchar時,程序就等著用戶按鍵,用戶輸入的字元被存放在鍵盤緩沖區中,直到用戶按回車為止(回車字元也放在緩沖區中)。當用戶鍵入回車之後,getchar才開始從stdin流中每次讀入一個字元,getchar函數的返回值是用戶輸入的第一個字元的ASCⅡ碼,如出錯返回-1,且將用戶輸入的字元回顯到屏幕。


如用戶在按回車之前輸入了不止一個字元,其他字元會保留在鍵盤緩存區中,等待後續getchar調用讀取。也就是說,後續的getchar調用不會等待用戶按鍵,而直接讀取緩沖區中的字元,直到緩沖區中的字元讀完為後,才等待用戶按鍵。


舉例如下:

charch;
ch=getchar();//接收用戶輸入的第一個字元,並賦值給字元變數ch返回值為輸入第一個字元的ASCII碼

H. 如何理解c/c++和php語言的區別

一、編程語言

1.根據熟悉的語言,談談兩種語言的區別?

主要淺談下C/C++和PHP語言的區別:

1)PHP弱類型語言,一種腳本語言,對數據的類型不要求過多,較多的應用於Web應用開發,現在好多互聯網開發公司的主流web後台開發語言,主要框架為mvc模型,如smarty,yaf,升級的PHP7速度較快,對伺服器的壓力要小很多,在新浪微博已經有應用,對比很明顯。

2)C/C++開發語言,C語言更偏向硬體底層開發,C++語言是目前為止我認為語法內容最多的一種語言。C/C++在執行速度上要快很多,畢竟其他類型的語言大都是C開發的,更多應用於網路編程和嵌入式編程。

2.volatile是幹啥用的,(必須將cpu的寄存器緩存機制回答得很透徹),使用實例有哪些?(重點)

1) 訪問寄存器比訪問內存單元要快,編譯器會優化減少內存的讀取,可能會讀臟數據。聲明變數為volatile,編譯器不再對訪問該變數的代碼優化,仍然從內存讀取,使訪問穩定。

總結:volatile關鍵詞影響編譯器編譯的結果,用volatile聲明的變數表示該變數隨時可能發生變化,與該變數有關的運算,不再編譯優化,以免出錯。

2)使用實例如下( 區分C程序員和嵌入式系統程序員的最基本的問題。 ):

並行設備的硬體寄存器(如:狀態寄存器)
一個中斷服務子程序中會訪問到的非自動變數(Non-automatic variables)
多線程應用中被幾個任務共享的變數
3)一個參數既可以是const還可以是volatile嗎?解釋為什麼。

可以。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。
4)一個指針可以是volatile 嗎?解釋為什麼。
可以。盡管這並不是很常見。一個例子當中斷服務子程序修改一個指向一個buffer的指針時。

下面的函數有什麼錯誤:
int square(volatile int *ptr) {
return *ptr * *ptr;
}
下面是答案:
這段代碼有點變態。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由於*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:
int square(volatile int *ptr){
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由於*ptr的值可能被意想不到地改變,因此a和b可能是不同的。結果,這段代碼可能並不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr){
int a;
a = *ptr;
return a * a;
}

更多linux內核視頻教程文本資料免費獲取後台私信【 內核 】。

3.static const等等的用法,(能說出越多越好)(重點)

² 首先說說const的用法(絕對不能說是常數)

1)在定義的時候必須進行初始化

2)指針可以是const 指針,也可以是指向const對象的指針

3)定義為const的形參,即在函數內部是不能被修改的

4)類的成員函數可以被聲明為正常成員函數,不能修改類的成員變數

5)類的成員函數可以返回的是常對象,即被const聲明的對象

6)類的成員變數是指成員變數不能在聲明時初始化,必須在構造函數的列表裡進行初始化

(註:千萬不要說const是個常數,會被認為是外行人的!!!!哪怕說個只讀也行)

下面的聲明都是什麼意思?
const int a; a是一個正常整型數
int const a; a是一個正常整型數
const int *a; a是一個指向常整型數的指針,整型數是不可修改的,但指針可以
int * const a; a為指向整型數的常指針,指針指向的整型數可以修改,但指針是不可修改的
int const * a const; a是一個指向常整型數的常指針,指針指向的整型數是不可修改的,同時指針也是不可修改的
通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。

Const如何做到只讀?

這些在編譯期間完成,對於內置類型,如int, 編譯器可能使用常數直接替換掉對此變數的引用。而對於結構體不一定。

² 再說說static的用法(三個明顯的作用一定要答出來)

1)在函數體內,一個被聲明為靜態的變數在這一函數被調用過程中維持其值不變。
2)在模塊內(但在函數體外),一個被聲明為靜態的變數可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變數。
3)在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用

4)類內的static成員變數屬於整個類所擁有,不能在類內進行定義,只能在類的作用域內進行定義

5)類內的static成員函數屬於整個類所擁有,不能包含this指針,只能調用static成員函數

static全局變數與普通的全局變數有什麼區別?static局部變數和普通局部變數有什麼區別?static函數與普通函數有什麼區別?

static全局變數與普通的全局變數有什麼區別:static全局變數只初始化一次,防止在其他文件單元中被引用;
static局部變數和普通局部變數有什麼區別:static局部變數只被初始化一次,下一次依據上一次結果值;
static函數與普通函數有什麼區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝

4.extern c 作用

告訴編譯器該段代碼以C語言進行編譯。

5.指針和引用的區別

1)引用是直接訪問,指針是間接訪問。

2)引用是變數的別名,本身不單獨分配自己的內存空間,而指針有自己的內存空間

3)引用綁定內存空間(必須賦初值),是一個變數別名不能更改綁定,可以改變對象的值。

總的來說:引用既具有指針的效率,又具有變數使用的方便性和直觀性

6. 關於靜態內存分配和動態內存分配的區別及過程

1) 靜態內存分配是在編譯時完成的,不佔用CPU資源;動態分配內存運行時完成,分配與釋放需要佔用CPU資源;

2)靜態內存分配是在棧上分配的,動態內存是堆上分配的;

3)動態內存分配需要指針或引用數據類型的支持,而靜態內存分配不需要;

4)靜態內存分配是按計劃分配,在編譯前確定內存塊的大小,動態內存分配運行時按需分配。

5)靜態分配內存是把內存的控制權交給了編譯器,動態內存把內存的控制權交給了程序員;

6)靜態分配內存的運行效率要比動態分配內存的效率要高,因為動態內存分配與釋放需要額外的開銷;動態內存管理水平嚴重依賴於程序員的水平,處理不當容易造成內存泄漏。

7. 頭文件中的 ifndef/define/endif 干什麼用

預處理,防止頭文件被重復使用,包括pragma once都是這樣的

8. 宏定義求兩個元素的最小值

#define MIN(A,B) ((A) next;

}

else

{

return NULL;

}

}

Node* pFind = pHead;

while (pCurrent) {

pFind = pFind->next;

pCurrent = pCurrent->next;

}

return pFind;

}

2. 給定一個單向鏈表(長度未知),請遍歷一次就找到中間的指針,假設該鏈表存儲在只讀存儲器,不能被修改

設置兩個指針,一個每次移動兩個位置,一個每次移動一個位置,當第一個指針到達尾節點時,第二個指針就達到了中間節點的位置

處理鏈表問題時,」快行指針「是一種很常見的技巧,快行指針指的是同時用兩個指針來迭代訪問鏈表,只不過其中一個比另一個超前一些。快指針往往先行幾步,或與慢指針相差固定的步數。

node *create() {

node *p1, *p2, *head;

int cycle = 1, x;

head = (node*)malloc(sizeof(node));

p1 = head;

while (cycle)

{

cout > x;

if (x != 0)

{

p2 = (node*)malloc(sizeof(node));

p2->data = x;

p1->next = p2;

p1 = p2;

}

else

{

cycle = 0;

}

}

head = head->next;

p1->next = NULL;

return head;

}

void findmid(node* head) {

node *p1, *p2, *mid;

p1 = head;

p2 = head;

while (p1->next->next != NULL)

{

p1 = p1->next->next;

p2 = p2->next;

mid = p2;

}

}

3. 將一個數組生成二叉排序樹

排序,選數組中間的一個元素作為根節點,左邊的元素構造左子樹,右邊的節點構造有子樹。

4. 查找數組中第k大的數字?

因為快排每次將數組劃分為兩組加一個樞紐元素,每一趟劃分你只需要將k與樞紐元素的下標進行比較,如果比樞紐元素下標大就從右邊的子數組中找,如果比樞紐元素下標小從左邊的子數組中找,如果一樣則就是樞紐元素,找到,如果需要從左邊或者右邊的子數組中再查找的話,只需要遞歸一邊查找即可,無需像快排一樣兩邊都需要遞歸,所以復雜度必然降低。

最差情況如下:假設快排每次都平均劃分,但是都不在樞紐元素上找到第k大第一趟快排沒找到,時間復雜度為O(n),第二趟也沒找到,時間復雜度為O(n/2),第k趟找到,時間復雜度為O(n/2k),所以總的時間復雜度為O(n(1+1/2+....+1/2k))=O(n),明顯比冒泡快,雖然遞歸深度是一樣的,但是每一趟時間復雜度降低。

5. 紅黑樹的定義和解釋?B樹的基本性質?

紅黑樹:

性質1. 節點是紅色或黑色。
性質2. 根節點是黑色。
性質3. 每個葉子結點都帶有兩個空的黑色結點(被稱為黑哨兵),如果一個結點n的只有一個左孩子,那麼n的右孩子是一個黑哨兵;如果結點n只有一個右孩子,那麼n的左孩子是一個黑哨兵。
性質4 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
性質5. 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

B樹:

1.所有非葉子結點至多擁有兩個兒子(Left和Right);

2.所有結點存儲一個關鍵字;

3.非葉子結點的左指針指向小於其關鍵字的子樹,右指針指向大於其關鍵字的子樹;

6. 常見的加密演算法?

對稱式加密就是加密和解密使用同一個密鑰。
非對稱式加密就是加密和解密所使用的不是同一個密鑰,通常有兩個密鑰,稱為「公鑰」和「私鑰」,它們兩個必需配對使用。
DES:對稱演算法,數據加密標准,速度較快,適用於加密大量數據的場合;
MD5的典型應用是對一段Message產生fingerprint(指紋),以防止被「篡改」。
RSA是第一個既能用於數據加密也能用於數字簽名的演算法。

7. https?

HTTP下加入SSL層,HTTPS的安全基礎是SSL。

8.有一個IP庫,給你一個IP,如何能夠快速的從中查找到對應的IP段?不用資料庫如何實現?要求省空間
9.簡述一致性hash演算法。

1)首先求memcached伺服器(節點)的哈希值,並將其配置到0 232的圓(continuum)。

2)然後採用同樣的方法求出存儲數據的鍵的哈希值,並映射到相同的圓上。

3)然後從數據映射到的位置開始順時針查找,將數據保存到找到的第一個伺服器上。如果超過232仍然找不到伺服器,就會保存到第一台memcached伺服器上。
11.描述一種hash table的實現方法

1) 除法散列法: p ,令 h(k ) = k mod p ,這里, p 如果選取的是比較大的素數,效果比較好。而且此法非常容易實現,因此是最常用的方法。最直觀的一種,上圖使用的就是這種散列法,公式: index = value % 16,求模數其實是通過一個除法運算得到的。

2) 平方散列法 :求index頻繁的操作,而乘法的運算要比除法來得省時。公式: index = (value * value) >> 28 (右移,除以2^28。記法:左移變大,是乘。右移變小,是除)

3) 數字選擇法:如果關鍵字的位數比較多,超過長整型範圍而無法直接運算,可以選擇其中數字分布比較均勻的若干位,所組成的新的值作為關鍵字或者直接作為函數值。

4) 斐波那契(Fibonacci)散列法:平方散列法的缺點是顯而易見的,通過找到一個理想的乘數index = (value * 2654435769) >> 28

沖突處理:令數組元素個數為 S ,則當 h(k) 已經存儲了元素的時候,依次探查 (h(k)+i) mod S , i=1,2,3…… ,直到找到空的存儲單元為止(或者從頭到尾掃描一圈仍未發現空單元,這就是哈希表已經滿了,發生了錯誤。當然這是可以通過擴大數組范圍避免的)。

12、各類樹結構的實現和應用

13、hash,任何一個技術面試官必問(例如為什麼一般hashtable的桶數會取一個素數?如何有效避免hash結果值的碰撞)

不選素數的話可能會造成hash出值的范圍和原定義的不一致

14.什麼是平衡二叉樹?

左右子樹都是平衡二叉樹,而且左右子樹的深度差值的約對值不大於1。

15.數組和鏈表的優缺點

數組,在內存上給出了連續的空間。鏈表,內存地址上可以是不連續的,每個鏈表的節點包括原來的內存和下一個節點的信息(單向的一個,雙向鏈表的話,會有兩個)。

數組優於鏈表的:

A. 內存空間佔用的少。

B. 數組內的數據可隨機訪問,但鏈表不具備隨機訪問性。

C. 查找速度快

鏈表優於數組的:

A. 插入與刪除的操作方便。

B. 內存地址的利用率方面鏈表好。

C. 方便內存地址擴展。

17.最小堆插入,刪除編程實現

18. 4G的long型整數中找到一個最大的,如何做?

每次從磁碟上盡量多讀一些數到內存區,然後處理完之後再讀入一批。減少IO次數,自然能夠提高效率。分批讀入選取最大數,再對緩存的最大數進行快排。

19. 有千萬個string在內存怎麼高速查找,插入和刪除?

對千萬個string做hash,可以實現高速查找,找到了,插入和刪除就很方便了。關鍵是如何做hash,對string做hash,要減少碰撞頻率。

在內存中維護一個大小為10000的最小堆,每次從文件讀一個數,與最小堆的堆頂元素比較,若比堆頂元素大,則替換掉堆頂元素,然後調整堆。最後剩下的堆內元素即為最大的1萬個數,演算法復雜度為O(NlogN)

(1)全局洗牌法

a)首先生成一個數組,大小為54,初始化為1~54

b)按照索引1到54,逐步對每一張索引牌進行洗牌,首先生成一個余數 value = rand %54,那麼我們的索引牌就和這個余數牌進行交換處理

c)等多索引到54結束後,一副牌就洗好了

(2)局部洗牌法:索引牌從1開始,到54結束。這一次索引牌只和剩下還沒有洗的牌進行交換, value = index + rand() %(54 - index)

演算法復雜度是O(n)

22.請分別用遞歸和非遞歸方法,先序遍歷二叉樹

24.其他各種排序方法

25.哈希表沖突解決方法?

常見的hash演算法如下:

解決沖突的方法:

也叫散列法,主要思想是當出現沖突的時候,以關鍵字的結果值作為key值輸入,再進行處理,依次直到沖突解決

線性地址再散列法

當沖突發生時,找到一個空的單元或者全表

二次探測再散列

沖突發生時,在表的左右兩側做跳躍式的探測

偽隨機探測再散列

同時構造不同的哈希函數

將同樣的哈希地址構造成一個同義詞的鏈表

建立一個基本表和溢出區,凡是和基本元素發生沖突都填入溢出區

六、系統架構

1.設計一個服務,提供遞增的SessionID服務,要求保證服務的高可靠性,有哪些方案?集中式/非集中式/分布式

2.多台伺服器要執行計劃任務,但只有拿到鎖的任務才能執行,有一個中心伺服器來負責分配鎖,但要保證服務的高可靠性。

3.如何有效的判斷伺服器是否存活?伺服器是否踢出集群的決策如何產生?

4.兩個伺服器如何在同一時刻獲取同一數據的時候保證只有一個伺服器能訪問到數據?

可以採用隊列進行處理,寫一個隊列介面保證同一時間只有一個進程能夠訪問到數據,或者對於存取資料庫的來說,資料庫也是可以加鎖處理的

5. 編寫高效伺服器程序,需要考慮的因素

性能對伺服器程序來說是至關重要的了,畢竟每個客戶都期望自己的請求能夠快速的得到響應並處理。那麼影響伺服器性能的首要因素應該是:

(1)系統的硬體資源,比如說CPU個數,速度,內存大小等。不過由於硬體技術的飛速發展,現代伺服器都不缺乏硬體資源。因此,需要考慮的主要問題是如何從「軟環境」來提升伺服器的性能。

伺服器的」軟環境「

(2)一方面是指系統的軟體資源,比如操作系統允許用戶打開的最大文件描述符數量

(3)另一方面指的就是伺服器程序本身,即如何從編程的角度來確保伺服器的性能。

主要就要考慮大量並發的處理這涉及到使用進程池或線程池實現高效的並發模式(半同步/半非同步和領導者/追隨者模式),以及高效的邏輯處理方式--有限狀態機內存的規劃使用比如使用內存池,以空間換時間,被事先創建好,避免動態分配,減少了伺服器對內核的訪問頻率,數據的復制,伺服器程序還應該避免不必要的數據復制,尤其是當數據復制發生在用戶空間和內核空間之間時。如果內核可以直接處理從socket或者文件讀入的數據,則應用程序就沒必要將這些數據從內核緩沖區拷貝到應用程序緩沖區中。這里所謂的「直接處理」,是指應用程序不關心這些數據的具體內容是什麼,不需要對它們作任何分析。比如說ftp伺服器,當客戶請求一個文件時,伺服器只需要檢測目標文件是否存在,以及是否有許可權讀取就可以了,不需要知道這個文件的具體內容,這樣的話ftp伺服器就不需要把目標文件讀入應用程序緩沖區然後調用send函數來發送,而是直接使用「零拷貝」函數sendfile直接將其發送給客戶端。另外,用戶代碼空間的數據賦值也應該盡可能的避免復制。當兩個工作進程之間需要傳遞大量的數據時,我們就應該考慮使用共享內存來在他們直接直接共享這些數據,而不是使用管道或者消息隊列來傳遞。上下文切換和鎖:並發程序必須考慮上下文的切換問題,即進程切換或線程切換所導致的系統開銷。即時I/O密集型伺服器也不應該使用過多的工作線程(或工作進程),否則進程間切換將佔用大量的CPU時間,伺服器真正處理業務邏輯的CPU時間比重就下降了。因此為每個客戶連接都創建一個工作線程是不可取的。應該使用某種高效的並發模式。(半同步半非同步或者說領導者追隨者模式)另一個問題就是共享資源的加鎖保護。鎖通常被認為是導致伺服器效率低下的一個因素,因為由他引入的代碼不僅不處理業務邏輯,而且需要訪問內核資源,因此如果伺服器有更好的解決方案,應該盡量避免使用鎖。或者說伺服器一定非要使用鎖的話,盡量使用細粒度的鎖,比如讀寫鎖,當工作線程都只讀一塊內存區域時,讀寫鎖不會增加系統開銷,而只有當需要寫時才真正需要鎖住這塊內存區域。對於高峰和低峰的伸縮處理,適度的緩存。

6. QQ飛車新用戶注冊時,如何判斷新注冊名字是否已存在?(數量級:幾億)

可以試下先將用戶名通過編碼方式轉換,如轉換64位整型。然後設置N個區間,每個區間為2^64/N的大小。對於新的用戶名,先通過2分尋找該用戶名屬於哪個區間,然後在在這個區間,做一個hash。對於不同的時間復雜度和內存要求可以設置不同N的大小~

加一些基礎的技術面試之外的職業素養的面試問題

1.你在工作中犯了個錯誤,有同事打你小報告,你如何處理?

a.同事之間應該培養和形成良好的同事關系,就是要互相支持而不是互相拆台,互相學習,互相幫助,共同進步。

b.如果小報告里邊的事情都是事實也就是說確實是本人做的不好不對的方面,那麼自己應該有則改之,提高自己。如果小報告里邊的事

情全部不是事實,就是說確實誣陷,那麼應該首先堅持日久見人心的態度,持之以恆的把本職工作做好,然後在必要的時候通過適當的

方式和領導溝通,相信領導會知道的。

2.你和同事合作完成一個任務,結果任務錯過了截止日期,你如何處理?

3.職業規劃?

4.離職原因?

5. 項目中遇到的難題,你是如何解決的?

A.時間 b要求 c.方法

I. Redis是什麼緩存機制

redis(RemoteDictionaryServer)遠程數據服務

內存高速緩存資料庫。C語言編寫,數據模型為key-value,NoSql資料庫。

希望對你有所啟發。apeit-程序猿IT中redis章節講的不錯,由淺入深,適合入門學習。

熱點內容
qq瀏覽器如何取消保存密碼 發布:2024-10-06 20:14:48 瀏覽:649
shell腳本ctrlc 發布:2024-10-06 20:10:37 瀏覽:888
壓縮板好嘛 發布:2024-10-06 20:10:28 瀏覽:670
java編譯基礎教程 發布:2024-10-06 20:09:47 瀏覽:268
我的世界電腦java怎麼玩伺服器 發布:2024-10-06 19:16:54 瀏覽:480
存儲空間大於存儲池中的可用容量 發布:2024-10-06 19:15:28 瀏覽:33
什麼叫估演算法 發布:2024-10-06 19:15:20 瀏覽:87
c語言庫編譯 發布:2024-10-06 19:09:23 瀏覽:747
啊里雲系統電視如何更換安卓系統 發布:2024-10-06 18:50:09 瀏覽:577
編譯語言分為幾類 發布:2024-10-06 18:34:56 瀏覽:785