|
2008年12月14日
灰度增強是一種在空域進行的圖像增強方法。它是指將一定范圍的像素(l,h)線性映射到一個新的范圍(nl,nh)的操作。如果原來某個位置(x,y)的像素p(x,y)在(l,h)的范圍內。那么,變換后的像素 f(p(x,y))=(p(x,y)-l)*(nh-nl)/(h-l);
使用gdi+對應的處理代碼如下:
void EnhanceImage_Linear(Bitmap *bmp, int oldLow,int oldHigh, int newLow,int newHigh) { ASSERT(bmp!=NULL); ASSERT(oldLow>=0 &&oldLow<=255); ASSERT(oldHigh>=0 &&oldHigh<=255); ASSERT(newLow>=0 &&newLow<=255); ASSERT(newHigh>=0 &&newHigh<=255); ASSERT(oldLow<oldHigh); ASSERT(newLow<newHigh);
long width=bmp->GetWidth(); long height=bmp->GetHeight(); BitmapData bmpData; bmp->LockBits(&Rect(0,0,width,height), ImageLockModeRead|ImageLockModeWrite,PixelFormat24bppRGB ,&bmpData); unsigned char *pStart=(unsigned char *)(bmpData.Scan0); REAL oldDiff=oldHigh-oldLow; REAL newDiff=newHigh-newLow; REAL ratio=newDiff/oldDiff; for(int j=0;j<height;j++) { for(int i=0;i<width;i++) { pStart+=j*bmpData.Stride+3*i; for(int k=0;k<3;k++) { if(pStart[k]>=oldLow &&pStart[k]<=oldHigh) { int data=((pStart[k]-oldLow)*ratio); if(data>255) { data=255; } pStart[k]=(unsigned char)data; } } } }
bmp->UnlockBits(&bmpData); }
圖像增強技術是將圖像的部分信息按照一定的要求加以強化,使得其更適合于某種應用要求。比如,我們可能覺得圖像的對比度太差,那么就可以將圖像的頻域中高頻信息加以強化,使得圖像的對比度更好;或者覺得圖像太過銳利了,那么可以增強圖像的低頻部分使得圖像得以平滑。 圖像增強可以在頻域或者空域進行。前者是只將圖像的空間一定位置的像素值pixel(x,y)按照一定的要求映射到另一個像素值f(pixel(x,y),這里的f就是我們的變換函數。后者(頻域增強)是指對圖像進行傅立葉變換等變換而獲取其像素變化的頻率信息,然后按照一定的要求將這些頻率信息處理以使之符合要求,然后將圖像變換回空間像素陣列。
2008年10月27日
第一階段 此階段主要是能熟練地使用某種語言。這就相當于練武中的套路和架式這些表面的東西。 第二階段 此階段能精通基于某種平臺的接口(例如我們現在常用的Win 32的API函數)以及所對應語言的自身的庫函數。到達這個階段后,也就相當于可以進行真實散打對練了,可以真正地在實踐中做些應用。 第三階段 此階段能深入地了解某個平臺系統的底層,已經具有了初級的內功的能力,也就是“手中有劍,心中無劍”。 第四階級 此階段能直接在平臺上進行比較深層次的開發?;旧?,能達到這個層次就可以說是進入了高層次。這時進入了高級內功的修煉。比如能進行VxD或操作系統的內核的修改。 這時已經不再有語言的束縛,語言只是一種工具,即使要用自己不會的語言進行開發,也只是簡單地熟悉一下,就手到擒來,完全不像是第一階段的時候學習語言的那種情況。一般來說,從第三階段過渡到第四階段是比較困難的。為什么會難呢?這就是因為很多人的思想變不過來。 第五階級 此階段就已經不再局限于簡單的技術上的問題了,而是能從全局上把握和設計一個比較大的系統體系結構,從內核到外層界面。可以說是“手中無劍,心中有劍”。到了這個階段以后,能對市面上的任何軟件進行剖析,并能按自己的要求進行設計,就算是MS Word這樣的大型軟件,只要有充足的時間,也一定會設計出來。 第六階級 此階段也是最高的境界,達到“無招勝有招”。這時候,任何問題就純粹變成了一個思路的問題,不是用什么代碼就能表示的。也就是“手中無劍,心中也無劍”。 此時,對于練功的人來說,他已不用再去學什么少林拳,只是在旁看一下少林拳的對戰,就能把此拳拿來就用。這就是真正的大師級的人物。這時,Win 32或Linux在你眼里是沒有什么差別的。 每一個階段再向上發展時都要按一定的方法。第一、第二個階段通過自學就可以完成,只要多用心去研究,耐心地去學習。 要想從第二個階段過渡到第三個階段,就要有一個好的學習環境。例如有一個高手帶領或公司里有一個好的練手環境。經過二、三年的積累就能達到第三個階段。但是,有些人到達第三個階段后,常常就很難有境界上的突破了。他們這時會產生一種觀念,認為軟件無非如此,認為自己已無所不能。其實,這時如果遇到大的或難些的軟件,他們往往還是無從下手。 現在我們國家大部分程序員都是在第二、三級之間。他們大多都是通過自學成才的,不過這樣的程序員一般在軟件公司也能獨當一面,完成一些軟件的模塊。 但是,也還有一
java方面的: it人資訊交流網 http://www.it315.org 這個網站是我最近才發現的,雖然內容不多,但是提供的相關java工具挺齊全。還有就是里面提供了java教學視頻錄象的免費下載,好像一兩周更換一段。個人覺得挺適合初學者的,尤其是那個classpath的設置,講的很透徹,大家有空可以看一看。
java官方站點(英文) http://java.sun.com 要想了解最新的java動態,下載最新的java相關,比如j2se、j2ee、j2se的最新jdk版本就來這里吧。
java中文站 http://www.java-cn.com 這個可能大家都知道,不用說了,他提供的java資源是最豐富的。注冊論壇是免費的,還送積分,用積分可以下載軟件和電子書等,如果積分用完了,就需要自己發表一些文章來賺新的積分。
中文java網站 http://www.cn-java.com 跟上面站點類似的一個站,宗旨就是:為java愛好者服務。值得一看!
鋒網 http://www.ijsp.net/tech/book/index.jsp 綜合性的java網站,內含“下載中心”、“教程教學”等欄目。
java動力 http://eww.cn 網站的內容可以,但是最為出色的是它所運用的flash技術,我就不在這里多說了,大家去看看就知道了,一個字“酷”?。?!
vc方面的: vc知識庫 http://www.vckbase.com 這個網站就不用多說了,學習vc必去之地。網站專門提供了免費的ftp下載,好東東巨多!
vc之路 http://www.vcroad.com 綜合軟件開發網站,以vc為主。“資源中心”有許多值得下載的東東。
visual c++/mfc開發指南 http://www.vchelp.net 以講述windows開發為主的站點,提供了最新的源代碼,開發工具,開發資料,開發教程和對好的開發站點,開發工具,圖書做介紹,同時為從事開發的朋友提供發布自己開發的軟件,代碼和工具場所。
c維視點 http://www.c-view.org/root/index.htm 最近發現的vc好站,書籍、軟件、代碼下載一應具全!??!
游戲開發: 風云工作室 http://member.netease.com/~cloudwu/2000/index.html
標點游戲制作 http://makegame.myetang.com/
未來開發者 http://www.fdev.net/
綜合的: 中國軟件網 http://www.csdn.net 中國最大的開發者網絡,他之所以著名就是因為他的論壇,大家有空可以去看看,能下到很多不錯的東東,另外也是交流學習的好地方。
電子書籍的: http://www.itebook.net
最后公布一個巨好的,狂多的電子書下載 http://www.pdown.net 還有巨好的 http://www.codestudy.net/default.asp
我會不斷完善這個帖子,要是斑竹允許,請置頂
(一)深入淺出理解索引結構
實際上,您可以把索引理解為一種特殊的目錄。微軟的SQL SERVER提供了兩種索引:聚集索引(clustered index,也稱聚類索引、簇集索引)和非聚集索引(nonclustered index,也稱非聚類索引、非簇集索引)。下面,我們舉例來說明一下聚集索引和非聚集索引的區別:
其實,我們的漢語字典的正文本身就是一個聚集索引。比如,我們要查“安”字,就會很自然地翻開字典的前幾頁,因為“安”的拼音是“an”,而按照拼音排序漢字的字典是以英文字母“a”開頭并以“z”結尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那么就說明您的字典中沒有這個字;同樣的,如果查“張”字,那您也會將您的字典翻到最后部分,因為“張”的拼音是“zhang”。也就是說,字典的正文部分本身就是一個目錄,您不需要再去查其他目錄來找到您需要找的內容。
我們把這種正文內容本身就是一種按照一定規則排列的目錄稱為“聚集索引”。
如果您認識某個字,您可以快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛才的方法找到您要查的字,而需要去根據“偏旁部首”查到您要找的字,然后根據這個字后的頁碼直接翻到某頁來找到您要找的字。但您結合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“張”字,我們可以看到在查部首之后的檢字表中“張”的頁碼是672頁,檢字表中“張”的上面是“馳”字,但頁碼卻是63頁,“張”的下面是“弩”字,頁面是390頁。很顯然,這些字并不是真正的分別位于“張”字的上下方,現在您看到的連續的“馳、張、弩”三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我們可以通過這種方式來找到您所需要的字,但它需要兩個過程,先找到目錄中的結果,然后再翻到您所需要的頁碼。
我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚集索引”。
通過以上例子,我們可以理解到什么是“聚集索引”和“非聚集索引”。
進一步引申一下,我們可以很容易的理解:每個表只能有一個聚集索引,因為目錄只能按照一種方法進行排序。
(二)何時使用聚集索引或非聚集索引
下面的表總結了何時使用聚集索引或非聚集索引(很重要)。
動作描述 使用聚集索引 使用非聚集索引
列經常被分組排序 應 應
返回某范圍內的數據 應 不應
一個或極少不同值 不應 不應
小數目的不同值 應 不應
大數目的不同值 不應 應
頻繁更新的列 不應 應
外鍵列 應 應
主鍵列 應 應
頻繁修改索引列 不應 應
事實上,我們可以通過前面聚集索引和非聚集索引的定義的例子來理解上表。如:返回某范圍內的數據一項。比如您的某個表有一個時間列,恰好您把聚合索引建立在了該列,這時您查詢2004年1月1日至2004年10月1日之間的全部數據時,這個速度就將是很快的,因為您的這本字典正文是按日期進行排序的,聚類索引只需要找到要檢索的所有數據中的開頭和結尾數據即可;而不像非聚集索引,必須先查到目錄中查到每一項數據對應的頁碼,然后再根據頁碼查到具體內容。
(三)結合實際,談索引使用的誤區
理論的目的是應用。雖然我們剛才列出了何時應使用聚集索引或非聚集索引,但在實踐中以上規則卻很容易被忽視或不能根據實際情況進行綜合分析。下面我們將根據在實踐中遇到的實際問題來談一下索引使用的誤區,以便于大家掌握索引建立的方法。
1、主鍵就是聚集索引
這種想法筆者認為是極端錯誤的,是對聚集索引的一種浪費。雖然SQL SERVER默認是在主鍵上建立聚集索引的。
通常,我們會在每個表中都建立一個ID列,以區分每條數據,并且這個ID列是自動增大的,步長一般為1。我們的這個辦公自動化的實例中的列Gid就是如此。此時,如果我們將這個列設為主鍵,SQL SERVER會將此列默認為聚集索引。這樣做有好處,就是可以讓您的數據在數據庫中按照ID進行物理排序,但筆者認為這樣做意義不大。
顯而易見,聚集索引的優勢是很明顯的,而每個表中只能有一個聚集索引的規則,這使得聚集索引變得更加珍貴。
從我們前面談到的聚集索引的定義我們可以看出,使用聚集索引的最大好處就是能夠根據查詢要求,迅速縮小查詢范圍,避免全表掃描。在實際應用中,因為ID號是自動生成的,我們并不知道每條記錄的ID號,所以我們很難在實踐中用ID號來進行查詢。這就使讓ID號這個主鍵作為聚集索引成為一種資源浪費。其次,讓每個ID號都不同的字段作為聚集索引也不符合“大數目的不同值情況下不應建立聚合索引”規則;當然,這種情況只是針對用戶經常修改記錄內容,特別是索引項的時候會負作用,但對于查詢速度并沒有影響。
在辦公自動化系統中,無論是系統首頁顯示的需要用戶簽收的文件、會議還是用戶進行文件查詢等任何情況下進行數據查詢都離不開字段的是“日期”還有用戶本身的“用戶名”。
通常,辦公自動化的首頁會顯示每個用戶尚未簽收的文件或會議。雖然我們的where語句可以僅僅限制當前用戶尚未簽收的情況,但如果您的系統已建立了很長時間,并且數據量很大,那么,每次每個用戶打開首頁的時候都進行一次全表掃描,這樣做意義是不大的,絕大多數的用戶1個月前的文件都已經瀏覽過了,這樣做只能徒增數據庫的開銷而已。事實上,我們完全可以讓用戶打開系統首頁時,數據庫僅僅查詢這個用戶近3個月來未閱覽的文件,通過“日期”這個字段來限制表掃描,提高查詢速度。如果您的辦公自動化系統已經建立的2年,那么您的首頁顯示速度理論上將是原來速度8倍,甚至更快。
在這里之所以提到“理論上”三字,是因為如果您的聚集索引還是盲目地建在ID這個主鍵上時,您的查詢速度是沒有這么高的,即使您在“日期”這個字段上建立的索引(非聚合索引)。下面我們就來看一下在1000萬條數據量的情況下各種查詢的速度表現(3個月內的數據為25萬條):
(1)僅在主鍵上建立聚集索引,并且不劃分時間段:
Select gid,fariqi,neibuyonghu,title from tgongwen
用時:128470毫秒(即:128秒)
(2)在主鍵上建立聚集索引,在fariq上建立非聚集索引:
select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi> dateadd(day,-90,getdate())
用時:53763毫秒(54秒)
(3)將聚合索引建立在日期列(fariqi)上:
select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi> dateadd(day,-90,getdate())
用時:2423毫秒(2秒)
雖然每條語句提取出來的都是25萬條數據,各種情況的差異卻是巨大的,特別是將聚集索引建立在日期列時的差異。事實上,如果您的數據庫真的有1000萬容量的話,把主鍵建立在ID列上,就像以上的第1、2種情況,在網頁上的表現就是超時,根本就無法顯示。這也是我摒棄ID列作為聚集索引的一個最重要的因素。
得出以上速度的方法是:在各個select語句前加:declare @d datetime
set @d=getdate()
并在select語句后加:
select [語句執行花費時間(毫秒)]=datediff(ms,@d,getdate())
2、只要建立索引就能顯著提高查詢速度
事實上,我們可以發現上面的例子中,第2、3條語句完全相同,且建立索引的字段也相同;不同的僅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查詢速度卻有著天壤之別。所以,并非是在任何字段上簡單地建立索引就能提高查詢速度。
從建表的語句中,我們可以看到這個有著1000萬數據的表中fariqi字段有5003個不同記錄。在此字段上建立聚合索引是再合適不過了。在現實中,我們每天都會發幾個文件,這幾個文件的發文日期就相同,這完全符合建立聚集索引要求的:“既不能絕大多數都相同,又不能只有極少數相同”的規則。由此看來,我們建立“適當”的聚合索引對于我們提高查詢速度是非常重要的。
3、把所有需要提高查詢速度的字段都加進聚集索引,以提高查詢速度
上面已經談到:在進行數據查詢時都離不開字段的是“日期”還有用戶本身的“用戶名”。既然這兩個字段都是如此的重要,我們可以把他們合并起來,建立一個復合索引(compound index)。
很多人認為只要把任何字段加進聚集索引,就能提高查詢速度,也有人感到迷惑:如果把復合的聚集索引字段分開查詢,那么查詢速度會減慢嗎?帶著這個問題,我們來看一下以下的查詢速度(結果集都是25萬條數據):(日期列fariqi首先排在復合聚集索引的起始列,用戶名neibuyonghu排在后列)
(1)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-5-5'
查詢速度:2513毫秒
(2)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-5-5' and neibuyonghu='辦公室'
查詢速度:2516毫秒
(3)select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu='辦公室'
查詢速度:60280毫秒
從以上試驗中,我們可以看到如果僅用聚集索引的起始列作為查詢條件和同時用到復合聚集索引的全部列的查詢速度是幾乎一樣的,甚至比用
2008年10月21日
__cdecl和__stdcall都是函數調用規范(還有一個__fastcall),規定了參數出入棧的順序和方法,如果只用VC編程的話可以不用關心,但是要在C++和Pascal等其他語言通信的時候就要注意了,只有用相同的方法才能夠調用成功.另外,像printf這樣接受可變個數參數的函數只有用cdecl才能夠實現. __declspec主要是用于說明DLL的引出函數的,在某些情況下用__declspec(dllexport)在DLL中生命引出函數,比用傳統的DEF文件方便一些.在普通程序中也可以用__declspec(dllimport)說明函數是位于另一個DLL中的導出函數.
int WINAPI MessageBoxA(HWND,LPCSTR,LPSTR,UINT); 而WINAPI實際上就是__stdcall. 大多數API都采用__stdcall調用規范,這是因為幾乎所有的語言都支持__stdcall調用.相比之下,__cdecl只有在C語言中才能用.但是__cdecl調用有一個特點,就是能夠實現可變參數的函數調用,比如printf,這用__stdcall調用是不可能的. __fastcall這種調用規范比較少見,但是在Borland C++ Builder中比較多的采用了這種調用方式. 如果有共享代碼的需要,比如寫DLL,推薦的方法是用__stdcall調用,因為這樣適用范圍最廣.如果是C++語言寫的代碼供Delphi這樣的語言調用就必須聲明為__stdcall,因為Pascal不支持cdecl調用(或許Delphi的最新版本能夠支持也說不定,這個我不太清楚).在其他一些地方,比如寫COM組件,幾乎都用的是stdcall調用.在VC或Delphi或C++Builder里面都可以從項目設置中更改默認的函數調用規范,當然你也可以在函數聲明的時候加入__stdcall,__cdecl,__fastcall關鍵字來明確的指示本函數用哪種調用規范. __declspec一般都是用來聲明DLL中的導出函數.這個關鍵字也有一些其他的用法,不過非常罕見.
2008年9月28日
#ifndef _ALV_TREE_H #define _ALV_TREE_H #define Max(a,b) (((a)>(b))?(a):(b)) #include <iostream>
template<class T> class AVLTree { struct _TreeNode; typedef struct _TreeNode TreeNode; struct _TreeNode { T data; int height; TreeNode* left; TreeNode* right; };
private: TreeNode *root; public: AVLTree() { this->root=NULL; }
~AVLTree() { this->MakeEmpty(this->root); }
int GeiHeight() { return this->GetHeightUtil(this->root); }
void Insert(T data) { this->root=this->InsertUtil(this->root,data); } void Delete(T data) { this->root=this->DeleteUtil(this->root,data); }
void Print() { /*if(root!=NULL) { std::cout<<"The root node is: "<<root->data<<std::endl; }*/ for(int level=0;;level++) { if(this->PrintUtil(this->root,level)==0) { break; } std::cout<<std::endl; } }
private: TreeNode *InsertUtil(TreeNode *_root,T data) { if(_root==NULL) { _root=new TreeNode(); _root->data=data; _root->left=0; _root->right=0; _root->height=0; } if(data>_root->data) { _root->right=this->InsertUtil(_root->right,data); if(GetHeightUtil(_root->right)-GetHeightUtil(_root->left)==2) { if(data>_root->right->data) { _root=this->SingleRotateWithRight(_root); } else { _root=this->DoubleRotateWithRight(_root); } } } else if(data<_root->data) { _root->left=this->InsertUtil(_root->left,data); if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(data<_root->left->data) { _root=this->SingleRotateWithLeft(_root); } else { _root=this->DoubleRotateWithLeft(_root); } } } _root->height=Max(GetHeightUtil(_root->left),GetHeightUtil(_root->right))+1; return _root; }
TreeNode *DeleteUtil(TreeNode *_root,T data) { if(_root==NULL) { return _root; } else if(_root->data==data &&_root->left==NULL &&_root->right==NULL) { delete _root; return NULL; } else if(_root->data==data &&_root->left!=NULL &&_root->right==NULL) { TreeNode* tmpNode=_root->left; delete _root; tmpNode->height=this->RecalculateHeight(tmpNode); return tmpNode; } else if(_root->data==data &&_root->left==NULL &&_root->right!=NULL) { TreeNode *tmpNode=_root->right; delete _root; tmpNode->height=this->RecalculateHeight(tmpNode); return tmpNode; } else { if(data==_root->data) { TreeNode *tmpNode,*parentNode; tmpNode=_root->right->right; parentNode=_root->right; if(tmpNode!=NULL) { while(tmpNode->right!=NULL) { parentNode->height-=1; parentNode=tmpNode; tmpNode=tmpNode->right; } parentNode->right=NULL; _root->data=tmpNode->data; delete tmpNode; } else { _root=parentNode; } _root->height=this->RecalculateHeight(_root); //TreeNode *tmpNode=this->FindMax(_root->right); //_root->data=tmpNode->data; if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(_root->left->left!=NULL) { _root=this->SingleRotateWithLeft(_root); } else if(_root->left->right!=NULL) { _root=this->DoubleRotateWithLeft(_root); } } } else if(data>_root->data) { _root->right=this->DeleteUtil(_root->right,data); _root->height=this->RecalculateHeight(_root); if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(_root->left->left!=NULL) { _root=this->SingleRotateWithLeft(_root); } else if(_root->left->right!=NULL) { _root=this->DoubleRotateWithLeft(_root); } } } else { _root->left=this->DeleteUtil(_root->left,data); _root->height=this->RecalculateHeight(_root); if(GetHeightUtil(_root->right)-GetHeightUtil(_root->left)==2) { if(_root->right->right!=NULL) { _root=this->SingleRotateWithRight(_root); } else if(_root->right->left!=NULL) { _root=this->DoubleRotateWithRight(_root); } } } } //_root->height=this->RecalculateHeight(_root); return _root; }
void MakeEmpty(TreeNode *_root) { if(_root==NULL) { return; } else { MakeEmpty(_root->left); MakeEmpty(_root->right); delete _root; } }
int GetHeightUtil(TreeNode *_root) { /*if(_root==NULL|| (_root->left==NULL && _root->right==NULL)) { return 0; } else { return 1+GetHeightUtil(_root->left)+GetHeightUtil(_root->right); }*/ if(_root==NULL) { return -1; } else { return _root->height; } }
int PrintUtil(TreeNode *node, int level) { if(node==NULL||level<0) { return 0; } else { if(level==0) { std::cout<<node->data<<" "; return 1; } return PrintUtil(node->left,level-1)+PrintUtil(node->right,level-1); } }
TreeNode *SingleRotateWithLeft(TreeNode *node) { TreeNode *tmpNode=node->left; node->left=tmpNode->right; tmpNode->right=node; node->height=Max(GetHeightUtil(node->left),GetHeightUtil(node->right))+1; tmpNode->height=Max(GetHeightUtil(tmpNode->left),GetHeightUtil(tmpNode->right))+1; return tmpNode; }
TreeNode*SingleRotateWithRight(TreeNode *node) { TreeNode *tmpNode=node->right; node->right=tmpNode->left; tmpNode->left=node; node->height=Max(GetHeightUtil(node->left),GetHeightUtil(node->right))+1; tmpNode->height=Max(GetHeightUtil(tmpNode->left),GetHeightUtil(tmpNode->right))+1; return tmpNode; }
TreeNode* DoubleRotateWithLeft(TreeNode *node) { node->left=this->SingleRotateWithRight(node->left); return this->SingleRotateWithLeft(node); }
TreeNode* DoubleRotateWithRight(TreeNode *node) { node->right=this->SingleRotateWithLeft(node->right); return this->SingleRotateWithRight(node); }
TreeNode* FindMax(TreeNode *node) { //T maxData; while(node!=NULL&&node->right!=NULL) { node=node->right; } //maxData=node->data; return node; }
int RecalculateHeight(TreeNode *node) { if(node==NULL) { return -1; } else { node->height=Max(RecalculateHeight(node->left),RecalculateHeight(node->right))+1; return node->height; } } };
#endif
首先打開菜單 項目->項目屬性頁
1。選擇配置屬性->鏈接器->調試->生成調試信息 改為 是
2。選擇 配置屬性->C/C++ ->常規->調試信息格式 改為 用于“編輯并繼續”的程序數據庫(/ZI)
3。選擇 配置屬性->C/C++ ->優化->優化 改為 自定義
重新編譯,運行
2008年9月23日
文本編輯器是所有計算機系統中最常用的一種工具。UNIX下的編輯器有ex,sed和vi等,其中,使用最為廣泛的是vi,而vi命令繁多,論壇里好像這方面的總結不多,以下稍做總結,以資共享!渴望更正和補充!
進入vi的命令 vi filename :打開或新建文件,并將光標置于第一行首 vi +n filename :打開文件,并將光標置于第n行首 vi + filename :打開文件,并將光標置于最后一行首 vi +/pattern filename:打開文件,并將光標置于第一個與pattern匹配的串處 vi -r filename :在上次正用vi編輯時發生系統崩潰,恢復filename vi filename....filename :打開多個文件,依次進行編輯
移動光標類命令 h :光標左移一個字符 l :光標右移一個字符 space:光標右移一個字符 Backspace:光標左移一個字符 k或Ctrl+p:光標上移一行 j或Ctrl+n :光標下移一行 Enter :光標下移一行 w或W :光標右移一個字至字首 b或B :光標左移一個字至字首 e或E :光標右移一個字至字尾 ) :光標移至句尾 ( :光標移至句首 }:光標移至段落開頭 {:光標移至段落結尾 nG:光標移至第n行首 n+:光標下移n行 n-:光標上移n行 n$:光標移至第n行尾 H :光標移至屏幕頂行 M :光標移至屏幕中間行 L :光標移至屏幕最后行 0:(注意是數字零)光標移至當前行首 $:光標移至當前行尾
屏幕翻滾類命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl+f:向文件尾翻一屏 Ctrl+b;向文件首翻一屏 nz:將第n行滾至屏幕頂部,不指定n時將當前行滾至屏幕頂部。
插入文本類命令 i :在光標前 I :在當前行首 a:光標后 A:在當前行尾 o:在當前行之下新開一行 O:在當前行之上新開一行 r:替換當前字符 R:替換當前字符及其后的字符,直至按ESC鍵 s:從當前光標位置處開始,以輸入的文本替代指定數目的字符 S:刪除指定數目的行,并以所輸入文本代替之 ncw或nCW:修改指定數目的字 nCC:修改指定數目的行
刪除命令 ndw或ndW:刪除光標處開始及其后的n-1個字 do:刪至行首 d$:刪至行尾 ndd:刪除當前行及其后n-1行 x或X:刪除一個字符,x刪除光標后的,而X刪除光標前的 Ctrl+u:刪除輸入方式下所輸入的文本
搜索及替換命令 /pattern:從光標開始處向文件尾搜索pattern ?pattern:從光標開始處向文件首搜索pattern n:在同一方向重復上一次搜索命令 N:在反方向上重復上一次搜索命令 :s/p1/p2/g:將當前行中所有p1均用p2替代 :n1,n2s/p1/p2/g:將第n1至n2行中所有p1均用p2替代 :g/p1/s//p2/g:將文件中所有p1均用p2替換
選項設置 all:列出所有選項設置情況 term:設置終端類型 ignorance:在搜索中忽略大小寫 list:顯示制表位(Ctrl+I)和行尾標志($) number:顯示行號 report:顯示由面向行的命令修改過的數目 terse:顯示簡短的警告信息 warn:在轉到別的文件時若沒保存當前文件則顯示NO write信息 nomagic:允許在搜索模式中,使用前面不帶“\”的特殊字符 nowrapscan:禁止vi在搜索到達文件兩端時,又從另一端開始 mesg:允許vi顯示其他用戶用write寫到自己終端上的信息
最后行方式命令 :n1,n2 co n3:將n1行到n2行之間的內容拷貝到第n3行下 :n1,n2 m n3:將n1行到n2行之間的內容移至到第n3行下 :n1,n2 d :將n1行到n2行之間的內容刪除 :w :保存當前文件 :e filename:打開文件filename進行編輯 :x:保存當前文件并退出 :q:退出vi :q!:不保存文件并退出vi :!command:執行shell命令command :n1,n2 w!command:將文件中n1行至n2行的內容作為command的輸入并執行之,若不指定n1,n2,則表示將整個文件內容作為command的輸入 :r!command:將命令command的輸出結果放到當前行
寄存器操作 "?nyy:將當前行及其下n行的內容保存到寄存器?中,其中?為一個字母,n為一個數字 "?nyw:將當前行及其下n個字保存到寄存器?中,其中?為一個字母,n為一個數字 "?nyl:將當前行及其下n個字符保存到寄存器?中,其中?為一個字母,n為一個數字 "?p:取出寄存器?中的內容并將其放到光標位置處。這里?可以是一個字母,也可以是一個數字 ndd:將當前行及其下共n行文本刪除,并將所刪內容放到1號刪除寄存器中。
代碼: #include <iostream> #include <windows.h> using namespace std;
int main() { SECURITY_ATTRIBUTES secStru; secStru.bInheritHandle=0; secStru.lpSecurityDescriptor=0; secStru.nLength=0; HANDLE hDevice=CreateFile("\\\\.\\PhysicalDrive0",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hDevice==INVALID_HANDLE_VALUE) { return -1; }
//DWORD outBuff[1000]; GET_LENGTH_INFORMATION infoStruct;
memset(&infoStruct,0,sizeof(infoStruct)); DWORD bytesReturned; if(DeviceIoControl(hDevice,IOCTL_DISK_GET_LENGTH_INFO,NULL,0,&infoStruct,sizeof(infoStruct),&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
DISK_GEOMETRY_EX geoStruct; memset(&geoStruct,0,sizeof(geoStruct)); if(DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY_EX ,NULL,0,&geoStruct,sizeof(geoStruct),&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
cout<<"The disk's size is:"<<infoStruct.Length.QuadPart/1024/1024/1024<<" G Bytes."<<endl; cout<<"The disk's cylinder number:"<<geoStruct.Geometry.Cylinders.QuadPart<<endl; cout<<"The disk's media type:"<<geoStruct.Geometry.MediaType<<endl; cout<<"Number of tracks per cylinder:"<<geoStruct.Geometry.TracksPerCylinder<<endl; cout<<"Number of sectors per track:"<<geoStruct.Geometry.SectorsPerTrack<<endl; cout<<"Number of bytes per sector:"<<geoStruct.Geometry.BytesPerSector<<endl;
PDISK_PARTITION_INFO partitionInfo=DiskGeometryGetPartition(&geoStruct);
DRIVE_LAYOUT_INFORMATION_EX layOutInfo[20];
memset(&layOutInfo,0,sizeof(DRIVE_LAYOUT_INFORMATION_EX)*20);
//layOutInfo.PartitionEntry=*(new PARTITION_INFORMATION_EX[10]);
if(DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_LAYOUT_EX,NULL,0,&layOutInfo,sizeof(DRIVE_LAYOUT_INFORMATION_EX)*20,&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
int partitionCount=layOutInfo[0].PartitionCount; cout<<"Number of partitions:"<<layOutInfo[0].PartitionCount<<endl; cout<<"Partitions' information:"<<endl; for(int i=0;i<partitionCount;i++) { //PDISK_PARTITION_INFO pParInfo=partitionInfo+i*sizeof(DISK_PARTITION_INFO); if(layOutInfo[i].PartitionEntry[0].PartitionNumber!=0) { cout<<"Partition "<<layOutInfo[i].PartitionEntry[0].PartitionNumber<<", partition size is "<<layOutInfo[i].PartitionEntry[0].PartitionLength.QuadPart/1024/1024/1024<<" G Bytes, partition style is "<<layOutInfo[i].PartitionEntry[0].PartitionStyle<<endl; } }
//cout<<"The type of partition:"<<((partitionInfo.PartitionStyle==PARTITION_STYLE_MBR) ?"MBR":((partitionInfo.PartitionStyle==PARTITION_STYLE_GPT )?"GPT":((partitionInfo.PartitionStyle==PARTITION_STYLE_RAW)?"RAW":"")))<<endl;
CloseHandle(hDevice);
return 0; }
|