• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tbwshc

            tbw

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              95 Posts :: 8 Stories :: 3 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(4)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            #

            什么是約瑟夫環(huán)呢?
              約瑟夫環(huán)是一個(gè)數(shù)學(xué)的應(yīng)用問題:已知n個(gè)人(以編號(hào)1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號(hào)為k的人開始報(bào)數(shù),數(shù)到m的那個(gè)人出列;他的下一個(gè)人又從1開始報(bào)數(shù),數(shù)到m的那個(gè)人又出列;依此規(guī)律重復(fù)下去,直到圓桌周圍的人全部出列。
              我們用程序說話,實(shí)現(xiàn)約瑟夫環(huán):

            import java.util.Scanner;
            public class Josephus{
             private static class Node{
              public int no;//編號(hào)
              public Node next;//下一個(gè)節(jié)點(diǎn)

             public Node(int no){
              this. no=no
             }
             }
            public static void main(String[]args)  {
                  SCanner scanner=new Scanner(System.in);
                  System.out.print('out. print("請(qǐng)輸入總?cè)藬?shù):");
                  int totalNum=scanner. nextInt);
                  System.out.print("請(qǐng)輸入報(bào)數(shù)的大小:");
                  int cycleNum=canner. nextInt();
                  Node heade==new Node(1);
                  Node pointer=heade;
                  for(int i=2;i<=totalNum;i++){
                       pointer.next=new Node(i);
                       pointer=pointer.next;
             }


            pointer=pointer. next;
            pointer. next=header;
            //初始化環(huán)形鏈表結(jié)束
            System.out.p:Intln("out. println("以下是出列tb的順序:‘)‘
            while (pointer!,pointer. next)  {
            for (int i=1;:<cycleNum; i++)
                pointer=pointer. next;
                }
                System.out.prlntln(pointer.next.no)out. println(pointer. next.no);
                pointer. next=pointer. next. next;
            }
            System. out. println(pointer.next.no);
            }
            }



            posted @ 2012-09-26 12:04 tbwshc 閱讀(947) | 評(píng)論 (-1)編輯 收藏

              在JAVA平臺(tái),實(shí)現(xiàn)異步調(diào)用的角色有如下三個(gè)角色:調(diào)用者 提貨單 真實(shí)數(shù)據(jù)一個(gè)調(diào)用者在調(diào)用耗時(shí)操作,不能立即返回?cái)?shù)據(jù)時(shí),先返回一個(gè)提貨單.然后在過一斷時(shí)間后憑提貨單來獲取真正的數(shù)據(jù).去蛋糕店買蛋糕,不需要等蛋糕做出來(假設(shè)現(xiàn)做要很長(zhǎng)時(shí)間),只需要領(lǐng)個(gè)提貨單就可以了(去干別的事情),等到蛋糕做好了,再拿提貨單取蛋糕就可以了。public class Main { public static void main(String[] args) {

              System.out.println("main BEGIN");

              Host host = new Host();

              Data data1 = host.request(10, 'A');

              Data data2 = host.request(20, 'B');

              Data data3 = host.request(30, 'C');

              System.out.println("main otherJob BEGIN");

              try {

              Thread.sleep(200);

              } catch (InterruptedException e) {

              }

              System.out.println("main otherJob END");

              System.out.println("data1 = " + data1.getContent());

              System.out.println("data2 = " + data2.getContent());

              System.out.println("data3 = " + data3.getContent());

              System.out.println("main END");

              }

              }

              這里的main類就相當(dāng)于“顧客”,host就相當(dāng)于“蛋糕店”,顧客向“蛋糕店”定蛋糕就相當(dāng)于“發(fā)請(qǐng)求request”,返回的數(shù)據(jù)data是FutureData的實(shí)例,就相當(dāng)于提貨單,而不是真正的“蛋糕”。在過一段時(shí)間后(sleep一段時(shí)間后),調(diào)用data1.getContent(),也就是tb拿提貨單獲取執(zhí)行結(jié)果。

              下面來看一下,顧客定蛋糕后,蛋糕店做了什么:

              public class Host {

              public Data request(final int count, final char c) {

              System.out.println("request(" + count + ", " + c + ") BEGIN");

              // (1) 建立FutureData的實(shí)體

              final FutureData future = new FutureData();

              // (2) 為了建立RealData的實(shí)體,啟動(dòng)新的線程

              new Thread() {

              public void run() {

              //在匿名內(nèi)部類中使用count、future、c。

              RealData realdata = new RealData(count, c);

              future.setRealData(realdata);

              }

              }.start();

              System.out.println("request(" + count + ", " + c + ") END");

              // (3) 取回FutureData實(shí)體,作為傳回值

              return future;

              }

              }

              host("蛋糕店")在接到請(qǐng)求后,先生成了“提貨單”FutureData的實(shí)例future,然后命令“蛋糕師傅”RealData去做蛋糕,realdata相當(dāng)于起個(gè)線程去做蛋糕了。然后host返回給顧客的僅僅是“提貨單”future,而不是蛋糕。當(dāng)?shù)案庾龊煤螅案鈳煾挡拍芙o對(duì)應(yīng)的“提貨單”蛋糕,也就是future.setRealData(realdata)。

            下面來看看蛋糕師傅是怎么做蛋糕的:

              建立一個(gè)字符串,包含count個(gè)c字符,為了表現(xiàn)出犯法需要花費(fèi)一些時(shí)間,使用了sleep。

              public class RealData implements Data { private final String content;

              public RealData(int count, char c) {

              System.out.println("making RealData(" + count + ", " + c + ") BEGIN");

              char[] buffer = new char[count];

              for (int i = 0; i < count; i++) {

              buffer[i] = c;

              try {

              Thread.sleep(1000);

              } catch (InterruptedException e) {

              }

              }

              System.out.println("making RealData(" + count + ", " + c + ") END");

              this.content = new String(buffer);

              }

              public String getContent() {

              return content;

              }

              }

              現(xiàn)在來看看“提貨單”future是怎么與蛋糕"content"對(duì)應(yīng)的:

              public class FutureData implements Data { private RealData realdata = null;

              private boolean ready = false;

              public synchronized void setRealData(RealData realdata) {

              if (ready) {

              return; // 防止setRealData被調(diào)用兩次以上。

              }

              this.realdata = realdata;

              this.ready = true;

              notifyAll();

              }

              public synchronized String getContent() {

              while (!ready) {

              try {

              wait();

              } catch (InterruptedException e) {

              }

              }

              return realdata.getContent();

              }

              }

              顧客做完自己的事情后,會(huì)拿著自己的“提貨單”來取蛋糕:

              System.out.println("data1 = " + data1.getContent());

              這時(shí)候如果蛋糕沒做好,就只好等了:

              while (!ready) { try {

              wait();

              } catch (InterruptedException e) {

              }

              //等做好后才能取到

              return realdata.getContent();

              程序分析

              對(duì)于每個(gè)請(qǐng)求,host都會(huì)生成一個(gè)線程,這個(gè)線程負(fù)責(zé)生成顧客需要的“蛋糕”。在等待一段時(shí)間以后,如果蛋糕還沒有做好,顧客還必須等待。直到“蛋糕被做好”,也就是

              future.setRealData(realdata); 執(zhí)行以后,顧客才能拿走蛋糕。

              每個(gè)線程只是專門負(fù)責(zé)制作特定顧客所需要的“蛋糕”。也就是顧客A對(duì)應(yīng)著蛋糕師傅A(chǔ),tb顧客B對(duì)應(yīng)著蛋糕師傅B。即使顧客B的蛋糕被先做好了,顧客A也只能等待蛋糕師傅A(chǔ)把蛋糕做好。換句話說,顧客之間沒有競(jìng)爭(zhēng)關(guān)系。

              類FutureData的兩個(gè)方法被設(shè)置為synchronized,實(shí)際上蛋糕師傅A(chǔ)與顧客A之間的互斥關(guān)系,也就是顧客A必須等待蛋糕師傅A(chǔ)把蛋糕做好后,才能拿走,而與蛋糕師傅B是否做好了蛋糕沒有關(guān)系。

             

            posted @ 2012-09-26 11:55 tbwshc 閱讀(687) | 評(píng)論 (0)編輯 收藏

            如果我們使用Oracle的oerr程序看看ORA-04068的定義,我們會(huì)得到下面的信息:
              $oerr ora 04068
              04068, 00000, "existing state of packages has been discarded"
              // *Cause: One of errors 4060 - 4067 when attempt to execute a stored procedure.
              // *Action: Try again after proper re-initialization of any
              // application's state.

              這個(gè)錯(cuò)誤顯示執(zhí)行包的現(xiàn)有狀態(tài)被另一個(gè)會(huì)話的一個(gè)動(dòng)作無效化了。這個(gè)“狀態(tài)”涉及包在規(guī)范或體中定義的任何全局變量(包括常量)。引起這個(gè)錯(cuò)誤的動(dòng)作一般是(但不局限于此)在得到了發(fā)生錯(cuò)誤的會(huì)話所使用的連接之后包的重新編譯。Oracle 建議的動(dòng)作是重新初始化應(yīng)用程序狀態(tài)以調(diào)整包的新狀態(tài)后重新嘗試。

             

            出現(xiàn)原因:

              一般是系統(tǒng)運(yùn)行過程中,對(duì)Package重新編譯,tbw會(huì)導(dǎo)致系統(tǒng)對(duì)于這個(gè)Session的Package失效。

            解決辦法:

              重啟業(yè)務(wù)系統(tǒng),重新獲得Oracle Session。

            避免方案:

              不要在系統(tǒng)運(yùn)行過程中,對(duì)Package重新編譯。



            傳說中的04068啊,這個(gè)錯(cuò)誤在開發(fā)中比較容易見到,簡(jiǎn)單說,就是你與數(shù)據(jù)庫(kù)建立鏈接后,這個(gè)package被編譯過,然后你再去調(diào)用這個(gè)包,會(huì)報(bào)這個(gè)錯(cuò)誤,但只會(huì)報(bào)一次。
            所以比較常見的做法,就是程序catch捕獲異常后,判斷錯(cuò)誤是否是04068,如果是,重新調(diào)用一次,第二次調(diào)用就沒問題了。
            posted @ 2012-09-24 15:47 tbwshc 閱讀(1272) | 評(píng)論 (0)編輯 收藏

            C語言宏定義技巧(常用宏定義)
               
                寫好C語言,漂亮的宏定義很重要,使用宏定義可以防止出錯(cuò),提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義……
               
                CODE:
               
                1,防止一個(gè)頭文件被重復(fù)包含
               
                #ifndef COMDEF_H
               
                #define COMDEF_H
               
                //頭文件內(nèi)容
               
                #endif
               
                2,重新定義一些類型,防止由于各種平臺(tái)和編譯器的不同tb ,而產(chǎn)生的類型字節(jié)數(shù)差異,方便移植。
               
                typedef unsigned char     boolean;   /* Boolean value type. */
               
                typedef unsigned long int uint32;     /* Unsigned 32 bit value */
               
                typedef unsigned short   uint16;     /* Unsigned 16 bit value */
               
                typedef unsigned char     uint8;     /* Unsigned 8 bit value */
               
                typedef signed long int   int32;     /* Signed 32 bit value */
               
                typedef signed short     int16;     /* Signed 16 bit value */
               
                typedef signed char     int8;     /* Signed 8 bit value */
               
                //下面的不建議使用
               
                typedef unsigned char   byte;       /* Unsigned 8 bit value type. */
               
                typedef unsigned short   word;       /* Unsinged 16 bit value type. */
               
                typedef unsigned long   dword;     /* Unsigned 32 bit value type. */
               
                typedef unsigned char   uint1;     /* Unsigned 8 bit value type. */
               
                typedef unsigned short   uint2;     /* Unsigned 16 bit value type. */
               
                typedef unsigned long   uint4;     /* Unsigned 32 bit value type. */
               
                typedef signed char     int1;       /* Signed 8 bit value type. */
               
                typedef signed short     int2;       /* Signed 16 bit value type. */
               
                typedef long int       int4;       /* Signed 32 bit value type. */
               
                typedef signed long     sint31;     /* Signed 32 bit value */
               
                typedef signed short     sint15;     /* Signed 16 bit value */
               
                typedef signed char     sint7;     /* Signed 8 bit value */
               
                3,得到指定地址上的一個(gè)字節(jié)或字
               
                #define MEM_B( x ) ( *( (byte *) (x) ) )
               
                #define MEM_W( x ) ( *( (word *) (x) ) )
               
                4,求最大值和最小值
               
                #define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
               
                #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
               
                5,得到一個(gè)field在結(jié)構(gòu)體(struct)中的偏移量
               
                #define FPOS( type, field ) \
               
                /*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
               
                6,得到一個(gè)結(jié)構(gòu)體中field所占用的字節(jié)數(shù)
               
                #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
               
                7,按照LSB格式把兩個(gè)字節(jié)轉(zhuǎn)化為一個(gè)Word
               
                #define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
               
                8,按照LSB格式把一個(gè)Word轉(zhuǎn)化為兩個(gè)字節(jié)
               
                #define FLOPW( ray, val ) \
               
                (ray)[0] = ((val) / 256); \
               
                (ray)[1] = ((val) & 0xFF)
               
                9,得到一個(gè)變量的地址(word寬度)
               
                #define B_PTR( var ) ( (byte *) (void *) &(var) )
               
                #define W_PTR( var ) ( (word *) (void *) &(var) )
               
                10,得到一個(gè)字的高位和低位字節(jié)
               
                #define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
               
                #define WORD_HI(xxx) ((byte) ((word)(xxx) 》 8))
               
                11,返回一個(gè)比X大的最接近的8的倍數(shù)
               
                #define RND8( x )     ((((x) + 7) / 8 ) * 8 )
               
                12,將一個(gè)字母轉(zhuǎn)換為大寫
               
                #define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z‘) ? ((c) - 0x20) : (c) )
               
                13,判斷字符是不是10進(jìn)值的數(shù)字
               
                #define DECCHK( c ) ((c) >= '0' && (c) <= '9’)
               
                14,判斷字符是不是16進(jìn)值的數(shù)字
               
                #define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9‘) ||\
               
                ((c) >= 'A' && (c) <= 'F’) ||\
               
                ((c) >= 'a' && (c) <= 'f‘) )
               
                15,防止溢出的一個(gè)方法
               
                #define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
               
                16,返回?cái)?shù)組元素的個(gè)數(shù)
               
                #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
               
                17,返回一個(gè)無符號(hào)數(shù)n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
               
                #define MOD_BY_POWER_OF_TWO( val, mod_by ) \
               
                ( (dword)(val) & (dword)((mod_by)-1) )
               
                18,對(duì)于IO空間映射在存儲(chǔ)空間的結(jié)構(gòu),輸入輸出處理
               
                #define inp(port)       (*((volatile byte *) (port)))
               
                #define inpw(port)     (*((volatile word *) (port)))
               
                #define inpdw(port)     (*((volatile dword *)(port)))
               
                #define outp(port, val)   (*((volatile byte *) (port)) = ((byte) (val)))
               
                #define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
               
                #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
               
                [2005-9-9添加]
               
                19,使用一些宏跟蹤調(diào)試
               
                A N S I標(biāo)準(zhǔn)說明了五個(gè)預(yù)定義的宏名。它們是:
               
                _ L I N E _
               
                _ F I L E _
               
                _ D A T E _
               
                _ T I M E _
               
                _ S T D C _
            如果編譯不是標(biāo)準(zhǔn)的,則可能僅支持以上宏名中的幾個(gè),或根本不支持。記住編譯程序
               
                也許還提供其它預(yù)定義的宏名。
               
                _ L I N E _及_ F I L E _宏指令在有關(guān)# l i n e的部分中已討論,這里討論其余的宏名。
               
                _ D AT E _宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時(shí)的日期。
               
                源代碼翻譯到目標(biāo)代碼的時(shí)間作為串包含在_ T I M E _中。串形式為時(shí):分:秒。
               
                如果實(shí)現(xiàn)是標(biāo)準(zhǔn)的,則宏_ S T D C _含有十進(jìn)制常量1.如果它含有任何其它數(shù),則實(shí)現(xiàn)是
               
                非標(biāo)準(zhǔn)的。
               
                可以定義宏,例如:
               
                當(dāng)定義了_DEBUG,輸出數(shù)據(jù)信息和所在文件所在行
               
                #ifdef _DEBUG
               
                #define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
               
                #else
               
                #define DEBUGMSG(msg,date)
               
                #endif
               
                20,宏定義防止使用是錯(cuò)誤
               
                用小括號(hào)包含。
               
                例如:#define ADD(a,b) (a+b)
               
                用do{}while(0)語句包含多語句防止錯(cuò)誤
               
                例如:#difne DO(a,b) a+b;\
               
                a++;
               
                應(yīng)用時(shí):if(…)
               
                DO(a,b); //產(chǎn)生錯(cuò)誤
               
                else
               
                解決方法: #difne DO(a,b) do{a+b;\
               
                a++;}while(0)
               
                宏中“#”和“##”的用法
               
                一、一般用法
               
                我們使用#把宏參數(shù)變?yōu)橐粋€(gè)字符串,用##把兩個(gè)宏參數(shù)貼合在一起。
               
                用法:
               
                #include<cstdio>
               
                #include<climits>
               
                using namespace std;
               
                #define STR(s)   #s
               
                #define CONS(a,b) int(a##e##b)
               
                int main()
               
                {
               
                printf(STR(vck));       // 輸出字符串“vck”
               
                printf(“%d\n”, CONS(2,3)); // 2e3 輸出:2000
               
                return 0;
               
                }
               
                二、當(dāng)宏參數(shù)是另一個(gè)宏的時(shí)候
               
                需要注意的是凡宏定義里有用'#’或‘##’的地方宏參數(shù)是不會(huì)再展開。
               
                1, 非‘#’和‘##’的情況
               
                #define TOW     (2)
               
                #define MUL(a,b) (a*b)
               
                printf(“%d*%d=%d\n”, TOW, TOW, MUL(TOW,TOW));
               
                這行的宏會(huì)被展開為:
               
                printf(“%d*%d=%d\n”, (2), (2), ((2)*(2)));
               
                MUL里的參數(shù)TOW會(huì)被展開為(2)。
               
                2, 當(dāng)有‘#’或‘##’的時(shí)候
               
                #define A       (2)
               
                #define STR(s)   #s
               
                #define CONS(a,b) int(a##e##b)
               
                printf(“int max: %s\n”, STR(INT_MAX));   // INT_MAX #include<climits>
               
                這行會(huì)被展開為:
               
                printf(“int max: %s\n”, “INT_MAX”);
               
                printf(“%s\n”, CONS(A, A));           // compile error
               
                這一行則是:
               
                printf(“%s\n”, int(AeA));
               
                INT_MAX和A都不會(huì)再被展開, 然而解決這個(gè)問題的方法很簡(jiǎn)單。 加多一層中間轉(zhuǎn)換宏。
               
                加這層宏的用意是把所有宏的參數(shù)在這層里全部展開, 那么在轉(zhuǎn)換宏里的那一個(gè)宏(_STR)就能得到正確的宏參數(shù)。
               
                #define A       (2)
               
                #define _STR(s)   #s
               
                #define STR(s)     _STR(s)       // 轉(zhuǎn)換宏
               
                #define _CONS(a,b) int(a##e##b)
               
                #define CONS(a,b)   _CONS(a,b)     // 轉(zhuǎn)換宏
               
                printf(“int max: %s\n”, STR(INT_MAX));       // INT_MAX,int型的最大值,為一個(gè)變量 #include<climits>
               
                輸出為: int max: 0x7fffffff
               
                STR(INT_MAX) --> _STR(0x7fffffff) 然后再轉(zhuǎn)換成字符串;
               
                printf(“%d\n”, CONS(A, A));
               
                輸出為:200
               
                CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))
               
                三、‘#’和‘##’的一些應(yīng)用特例
               
                1、合并匿名變量名
               
                #define ___ANONYMOUS1(type, var, line) type var##line
               
                #define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
               
                #define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
               
                例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示該行行號(hào);
               
                第一層:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
               
                第二層:                 --> ___ANONYMOUS1(static int, _anonymous, 70);
               
                第三層:                 --> static int _anonymous70;
               
                即每次只能解開當(dāng)前層的宏,所以__LINE__在第二層才能被解開;
               
                2、填充結(jié)構(gòu)
               
                #define FILL(a)   {a, #a}
               
                enum IDD{OPEN, CLOSE};
               
                typedef struct MSG{
               
                IDD id;
               
                const char * msg;
               
                }MSG;
               
                MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
               
                相當(dāng)于:
               
                MSG _msg[] = {{OPEN, “OPEN”},
               
                {CLOSE, “CLOSE”}};
               
                3、記錄文件名
               
                #define _GET_FILE_NAME(f)   #f
               
                #define GET_FILE_NAME(f)   _GET_FILE_NAME(f)
               
                static char FILE_NAME[] = GET_FILE_NAME(__FILE__);
               
                4、得到一個(gè)數(shù)值類型所對(duì)應(yīng)的字符串緩沖大小
               
                #define _TYPE_BUF_SIZE(type) sizeof #type
               
                #define TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)
               
                char buf[TYPE_BUF_SIZE(INT_MAX)];
               
                --> char buf[_TYPE_BUF_SIZE(0x7fffffff)];
               
                --> char buf[sizeof “0x7fffffff”];
               
                這里相當(dāng)于:
               
            posted @ 2012-09-22 17:59 tbwshc 閱讀(217) | 評(píng)論 (0)編輯 收藏

             二叉堆的實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)中如何使用,我任務(wù)主要是在操作系統(tǒng)中的任務(wù)優(yōu)先級(jí)調(diào)度問題,當(dāng)然也可以用于實(shí)現(xiàn)堆排序問題,比如找出數(shù)組中的第K個(gè)最小值問題,采用二叉堆能夠快速的實(shí)現(xiàn),今天我就采用C語言實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的二叉堆操作,完成這些數(shù)據(jù)結(jié)構(gòu)我并不知道能干什么,我就當(dāng)自己在練習(xí)C語言的功底吧。逐步完成自己的代碼,希望自己在知識(shí)的理解力上有一定的提高。

                二叉堆是非常有特點(diǎn)的數(shù)據(jù)結(jié)構(gòu),可以采用簡(jiǎn)單的數(shù)組就能實(shí)現(xiàn),當(dāng)然鏈表的實(shí)現(xiàn)也是沒有問題的,畢竟是一個(gè)二叉樹問題,當(dāng)然可以采用鏈表實(shí)現(xiàn)。采用數(shù)組實(shí)現(xiàn)時(shí),可以找到兩個(gè)特別明顯的規(guī)律:

                左兒子:L_Son = Parent * 2;

                右兒子:R_Son = Parent * 2 + 1;

                二叉堆是一顆完全填滿的樹,可能例外的是在底層,底層上的元素是從左到右填入,當(dāng)然二叉堆可以是基于大值的排序,也可以是基于小值的排列形式,本文采用簡(jiǎn)單的基于小值的形式。主要完成的操作:1、最小值的刪除操作,該操作會(huì)刪除根節(jié)點(diǎn),然后提升兒子節(jié)點(diǎn)來代替根節(jié)點(diǎn),具體的實(shí)現(xiàn)過程中通過提升左右兒子中較小的作為父結(jié)點(diǎn),依此提升直到到達(dá)最底層,這種實(shí)現(xiàn)方式叫做下慮法。2、數(shù)據(jù)的插入操作,插入操作可能會(huì)破壞二叉堆的結(jié)構(gòu),一般在最底層創(chuàng)建一個(gè)空穴,然后比較插入值與空穴父結(jié)點(diǎn)的值,如果大于父結(jié)點(diǎn)的值,那么直接插入到空穴中,如果小于父結(jié)點(diǎn),則將父結(jié)點(diǎn)的值插入到剛創(chuàng)建的空穴中,在父結(jié)點(diǎn)所在位置上形成新的父結(jié)點(diǎn),這時(shí)候再和父結(jié)點(diǎn)的父結(jié)點(diǎn)比較,具體操作如上所述,直到找到具體的插入地址。當(dāng)結(jié)點(diǎn)個(gè)數(shù)為偶數(shù)時(shí),在刪除操作中需要注意節(jié)點(diǎn)是否有右兒子的情況。具體的可以參考代碼中的說明。

                具體的實(shí)現(xiàn)如下:

                結(jié)構(gòu)體:

                #ifndef __BINARYHEAP_H_H_

                #define __BINARYHEAP_H_H_

                #include <stdlib.h>

                #include <assert.h>

                #define bool int

                #define true 1

                #define false 0

                /*打算采用數(shù)組的方式實(shí)現(xiàn)完全二叉堆*/

                typedef struct _binaryheap

                {

                /*因?yàn)樾枰獎(jiǎng)討B(tài)擴(kuò)展,

                *采用靜態(tài)數(shù)組不方便*/

                int * parray;

                /*目前存在的結(jié)點(diǎn)*/

                int currentSize;

                /*樹的實(shí)際容量*/

                int capacity;

                }BinaryHeap_t, *BinaryHeap_handle_t;

                #ifdef __cplusplus

                extern "C"

                {

                #endif

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity);

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity);

                void delete_BinaryHeap(BinaryHeap_handle_t heap);

                void free_BinaryHeap(BinaryHeap_handle_t *heap);

                bool insert(BinaryHeap_handle_t heap,int value);

                int deleteMin(BinaryHeap_handle_t heap);

                bool isEmpty(BinaryHeap_handle_t heap);

                #ifdef __cplusplus

                }

                #endif

                #endif

                實(shí)現(xiàn)的接口函數(shù)如下:

                #include "binaryheap.h"

                bool isEmpty(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL);

                return heap->currentSize == 0;

                }

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity)

                {

                int *parray = NULL;

                if(heap == NULL)

                return false;

                parray = (int *)calloc(capacity+1,sizeof(int));

                if(parray == NULL)

                return false;

                heap->parray = parray;

                heap->capacity = capacity;

                heap->currentSize = 0;

                return true;

                }

                void delete_BinaryHeap(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL && heap->parray != NULL);

                heap->capacity = 0;

                heap->currentSize = 0;

                free(heap->parray);

                heap->parray = NULL;

                }

                void free_BinaryHeap(BinaryHeap_handle_t *heap)

                {

                assert(*heap != NULL);

                (*heap)->capacity = 0;

                (*heap)->currentSize = 0;

                free((*heap)->parray);

                (*heap)->parray = NULL;

                free(*heap);

                *heap = NULL;

                }

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity)

                {

                int *parray = NULL;

                if(*heap != NULL)

                return false;

                *heap = (int *)calloc(1, sizeof(BinaryHeap_t));

                if(*heap == NULL)

                return false;

                /*其中的1,主要是為了使得數(shù)組從下標(biāo)1開始計(jì)算*/

                parray =(int *)calloc(capacity + 1, sizeof(int));

                if(parray == NULL)

                return false;

                (*heap)->parray = parray;

                (*heap)->capacity = capacity;

                (*heap)->currentSize = 0;

                return true;

                }

                /**************************************************

                * 采用上慮法實(shí)現(xiàn)數(shù)據(jù)的插入操作

                * 上慮法的實(shí)現(xiàn)方式比較簡(jiǎn)單,首先創(chuàng)建一個(gè)空節(jié)點(diǎn)

                * 然后將需要插入的值與當(dāng)前空穴的父結(jié)點(diǎn)進(jìn)行比較

                * 如果大于父結(jié)點(diǎn),直接插入空穴中

                * 如果小于父結(jié)點(diǎn)的值,則將父結(jié)點(diǎn)的值下拉到空穴中

                * 之前父結(jié)點(diǎn)的位置就是空穴,接著與上層比較

                * 直到找到父結(jié)點(diǎn)大于當(dāng)前插入值的情況

                **************************************************/

                bool insert(BinaryHeap_handle_t heap, int value)

                {

                int index = 0;

                if(heap == NULL || heap->parray == NULL)

                return false;

                /*得到一個(gè)新的空穴下標(biāo)*/

                index = ++heap->currentSize;

                /*條件是不是第一個(gè)下標(biāo)和插入值比對(duì)應(yīng)父結(jié)點(diǎn)小*/

                while(index > 1 && value < heap->parray[index/2])

                {

                /*將父結(jié)點(diǎn)保存到當(dāng)前結(jié)點(diǎn)處*/

                heap->parray[index] = heap->parray[index/2];

                /*得到父結(jié)點(diǎn)的空穴位置*/

                index /= 2;

                }

                /*將插入的值保存到剩余的空穴中*/

                heap->parray[index] = value;

                return true;

                }

                /***********************************************************

                * 下慮法實(shí)現(xiàn)數(shù)據(jù)的重排序操作

                * 實(shí)現(xiàn)的方式,將子結(jié)點(diǎn)的兩個(gè)兒子進(jìn)行比較,將小的提升

                * 需要注意的是如何讓判斷節(jié)點(diǎn)是否一定存在右兒子

                * 實(shí)現(xiàn)的方式主要是利用了二叉堆的特性:

                * 2*pare = L_child

                * 2*pare + 1 = R_child;

                ***********************************************************/

                static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

                {

                /*這是二叉堆的特性*/

                int child = hole * 2;

                /*保存當(dāng)前數(shù)據(jù)操作*/

                int tmp = 0;

                assert(heap != NULL && heap->parray != NULL);

                tmp = heap->parray[hole];

                /*hold * 2 <= heap->currentSize 判斷了當(dāng)前結(jié)點(diǎn)是否為最低層*/

                for(; hole * 2 <= heap->currentSize; hole = child)

                {

                child = hole * 2;

                /*******************************

                *這句代碼解決是否存在右結(jié)點(diǎn)的問題

                *并確定了那個(gè)子結(jié)點(diǎn)提升的問題

                *******************************/

                if((child != heap->currentSize)

                && (heap->parray[child + 1] < heap->parray[child]))

                child ++;

                if(heap->parray[child] < tmp)

                {

                /*將子結(jié)點(diǎn)提升為父結(jié)點(diǎn)*/

                heap->parray[hole] = heap->parray[child];

                }

                }

                /*到達(dá)了最低的層,也就是樹葉*/

                heap->parray[hole] = tmp;

                }

                /*實(shí)現(xiàn)數(shù)據(jù)的下慮法實(shí)現(xiàn)數(shù)據(jù)的刪除操作*/

                int deleteMin(BinaryHeap_handle_t heap)

                {

                int ret = 0;

                int index = 0;

                assert(!isEmpty(heap));

                /*需要返回的值*/

                ret = heap->parray[1];

                /*將最后需要釋放內(nèi)存空間的值保存到第一個(gè)內(nèi)存空間中*/

                heap->parray[1] = heap->parray[heap->currentSize --];

                /*從表頭開始將新的二叉樹進(jìn)行重新排序*/

                presort_BinaryHeap(heap, 1);

                return ret;

                }

                測(cè)試代碼:

                #include "binaryheap.h"

                #include <stdio.h>

                #include <time.h>

                void print_binaryheap(BinaryHeap_handle_t heap)[nettpage]

                {

                int i = 0;

                assert(heap != NULL && heap->parray != NULL);

                for(i = 1; i <= heap->currentSize; ++ i)

                {

                if(i %6)

                printf("%d\t",heap->parray[i]);

                else

                printf("\n%d\t",heap->parray[i]);

                }

                printf("\n");

                }

                int main()

                {

                int i = 0;

                int value = 0;

                srand((int)time(0));

                printf("********Test Binaryheap**************\n");

                BinaryHeap_t bheap;

                BinaryHeap_handle_t *pheap = NULL;

                printf("init and alloc test:\n");

                if(init_BinaryHeap(&bheap,10))

                {

                printf("init_BinaryHeap() successed!\n");

                }

                if (alloc_BinaryHeap(&pheap,15));

                {

                printf("alloc_BInaryHeap() successed!\n");

                }

                printf("***insert test*****\n");

                for(; i < 10; ++ i)

                {

                if(!insert(&bheap,5 * i - rand()%20))

                {

                printf("i = %d:insert failed !!\n",i);

                }

                }

                for(i = 0; i < 15; ++ i)

                {

                if(!insert(pheap,i * 8 - rand()%20))

                {

                printf("i = %d:insert failed!!\n",i);

                }

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("****deleteMin test****\n");

                for(i = 0; i < 5; ++ i)

                {

                value = deleteMin(&bheap);

                printf("bheap deleted:%d\n",value);

                value = deleteMin(pheap);

                printf("pheap deleted:%d\n",value);

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("deleteMin test successed\n");

                printf("****delete and free test:*******\n");

                delete_BinaryHeap(&bheap);

                printf("Is the bheap empty ? %s\n",

                isEmpty(&bheap)?"Yes":"No");

                free_BinaryHeap(&pheap);

                printf("*********Test successed!***********\n");

                pheap = NULL;

                return 0;

                }

                測(cè)試結(jié)果:

                [gong@Gong-Computer c_binaryheap]$ ./testbinaryheap

                ********Test Binaryheap**************

                init and alloc test:

                init_BinaryHeap()

                alloc_BInaryHeap()

                ***insert test*****

                -11    -9    -9    14    15

                10    21    23    40    26

                -16    2    14    20    13

                21    33    49    61    67    76

                86    83    95    109

                ****deleteMin test****

                bheap deleted:-11

                pheap deleted:-16

                bheap deleted:-9

                pheap deleted:2

                bheap deleted:-9

                pheap deleted:13

                bheap deleted:10

                pheap deleted:14

                bheap deleted:14

                pheap deleted:20

                15    23    21    40    26

                21    49    21    61    67

                76    33    95    83    109

                deleteMin test successed

                ****delete and free test:*******

                Is the bheap empty ? Yes

                *********Test

                從上面的測(cè)試結(jié)果可知,基本上實(shí)現(xiàn)了二叉堆的基本插入、刪除操作。代碼的關(guān)鍵點(diǎn)在于刪除中的下慮和插入過程中的上慮操作。以及如何判斷代碼是否存在右兒子,如何充分運(yùn)用二叉堆的特性。    二叉堆的實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)中如何使用,我任務(wù)主要是在操作系統(tǒng)中的任務(wù)優(yōu)先級(jí)調(diào)度問題,當(dāng)然也可以用于實(shí)現(xiàn)堆排序問題,比如找出數(shù)組中的第K個(gè)最小值問題,采用二叉堆能夠快速的實(shí)現(xiàn),今天我就采用C語言實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的二叉堆操作,完成這些數(shù)據(jù)結(jié)構(gòu)我并不知道能干什么,我就當(dāng)自己在練習(xí)C語言的功底吧。逐步完成自己的代碼,希望自己在知識(shí)的理解力上有一定的提高。

                二叉堆是非常有特點(diǎn)的數(shù)據(jù)結(jié)構(gòu),可以采用簡(jiǎn)單的數(shù)組就能實(shí)現(xiàn),當(dāng)然鏈表的實(shí)現(xiàn)也是沒有問題的,畢竟是一個(gè)二叉樹問題,當(dāng)然可以采用鏈表實(shí)現(xiàn)。采用數(shù)組實(shí)現(xiàn)時(shí),可以找到兩個(gè)特別明顯的規(guī)律:

                左兒子:L_Son = Parent * 2;

                右兒子:R_Son = Parent * 2 + 1;

                二叉堆是一顆完全填滿的樹,可能例外的是在底層,底層上的元素是從左到右填入,當(dāng)然二叉堆可以是基于大值的排序,也可以是基于小值的排列形式,本文采用簡(jiǎn)單的基于小值的形式。主要完成的操作:1、最小值的刪除操作,該操作會(huì)刪除根節(jié)點(diǎn),然后提升兒子節(jié)點(diǎn)來代替根節(jié)點(diǎn),具體的實(shí)現(xiàn)過程中通過提升左右兒子中較小的作為父結(jié)點(diǎn),依此提升直到到達(dá)最底層,這種實(shí)現(xiàn)方式叫做下慮法。2、數(shù)據(jù)的插入操作,插入操作可能會(huì)破壞二叉堆的結(jié)構(gòu),一般在最底層創(chuàng)建一個(gè)空穴,然后比較插入值與空穴父結(jié)點(diǎn)的值,如果大于父結(jié)點(diǎn)的值,那么直接插入到空穴中,如果小于父結(jié)點(diǎn),則將父結(jié)點(diǎn)的值插入到剛創(chuàng)建的空穴中,在父結(jié)點(diǎn)所在位置上形成新的父結(jié)點(diǎn),這時(shí)候再和父結(jié)點(diǎn)的父結(jié)點(diǎn)比較,具體操作如上所述,直到找到具體的插入地址。當(dāng)結(jié)點(diǎn)個(gè)數(shù)為偶數(shù)時(shí),在刪除操作中需要注意節(jié)點(diǎn)是否有右兒子的情況。具體的可以參考代碼中的說明。

                具體的實(shí)現(xiàn)如下:

                結(jié)構(gòu)體:

                #ifndef __BINARYHEAP_H_H_

                #define __BINARYHEAP_H_H_

                #include <stdlib.h>

                #include <assert.h>

                #define bool int

                #define true 1

                #define false 0

                /*打算采用數(shù)組的方式實(shí)現(xiàn)完全二叉堆*/

                typedef struct _binaryheap

                {

                /*因?yàn)樾枰獎(jiǎng)討B(tài)擴(kuò)展,

                *采用靜態(tài)數(shù)組不方便*/

                int * parray;

                /*目前存在的結(jié)點(diǎn)*/

                int currentSize;

                /*樹的實(shí)際容量*/

                int capacity;

                }BinaryHeap_t, *BinaryHeap_handle_t;

                #ifdef __cplusplus

                extern "C"

                {

                #endif

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity);

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity);

                void delete_BinaryHeap(BinaryHeap_handle_t heap);

                void free_BinaryHeap(BinaryHeap_handle_t *heap);

                bool insert(BinaryHeap_handle_t heap,int value);

                int deleteMin(BinaryHeap_handle_t heap);

                bool isEmpty(BinaryHeap_handle_t heap);

                #ifdef __cplusplus

                }

                #endif

                #endif

                實(shí)現(xiàn)的接口函數(shù)如下:

                #include "binaryheap.h"

                bool isEmpty(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL);

                return heap->currentSize == 0;

                }

                bool init_BinaryHeap(BinaryHeap_handle_t heap, int capacity)

                {

                int *parray = NULL;

                if(heap == NULL)

                return false;

                parray = (int *)calloc(capacity+1,sizeof(int));

                if(parray == NULL)

                return false;

                heap->parray = parray;

                heap->capacity = capacity;

                heap->currentSize = 0;

                return true;

                }

                void delete_BinaryHeap(BinaryHeap_handle_t heap)

                {

                assert(heap != NULL && heap->parray != NULL);

                heap->capacity = 0;

                heap->currentSize = 0;

                free(heap->parray);

                heap->parray = NULL;

                }

                void free_BinaryHeap(BinaryHeap_handle_t *heap)

                {

                assert(*heap != NULL);

                (*heap)->capacity = 0;

                (*heap)->currentSize = 0;

                free((*heap)->parray);

                (*heap)->parray = NULL;

                free(*heap);

                *heap = NULL;

                }

                bool alloc_BinaryHeap(BinaryHeap_handle_t *heap, int capacity)

                {

                int *parray = NULL;

                if(*heap != NULL)

                return false;

                *heap = (int *)calloc(1, sizeof(BinaryHeap_t));

                if(*heap == NULL)

                return false;

                /*其中的1,主要是為了使得數(shù)組從下標(biāo)1開始計(jì)算*/

                parray =(int *)calloc(capacity + 1, sizeof(int));

                if(parray == NULL)

                return false;

                (*heap)->parray = parray;

                (*heap)->capacity = capacity;

                (*heap)->currentSize = 0;

                return true;

                }

                /**************************************************

                * 采用上慮法實(shí)現(xiàn)數(shù)據(jù)的插入操作

                * 上慮法的實(shí)現(xiàn)方式比較簡(jiǎn)單,首先創(chuàng)建一個(gè)空節(jié)點(diǎn)

                * 然后將需要插入的值與當(dāng)前空穴的父結(jié)點(diǎn)進(jìn)行比較

                * 如果大于父結(jié)點(diǎn),直接插入空穴中

                * 如果小于父結(jié)點(diǎn)的值,則將父結(jié)點(diǎn)的值下拉到空穴中

                * 之前父結(jié)點(diǎn)的位置就是空穴,接著與上層比較

                * 直到找到父結(jié)點(diǎn)大于當(dāng)前插入值的情況

                **************************************************/

                bool insert(BinaryHeap_handle_t heap, int value)

                {

                int index = 0;

                if(heap == NULL || heap->parray == NULL)

                return false;

                /*得到一個(gè)新的空穴下標(biāo)*/

                index = ++heap->currentSize;

                /*條件是不是第一個(gè)下標(biāo)和插入值比對(duì)應(yīng)父結(jié)點(diǎn)小*/


            while(index > 1 && value < heap->parray[index/2])

                {

                /*將父結(jié)點(diǎn)保存到當(dāng)前結(jié)點(diǎn)處*/

                heap->parray[index] = heap->parray[index/2];

                /*得到父結(jié)點(diǎn)的空穴位置*/

                index /= 2;

                }

                /*將插入的值保存到剩余的空穴中*/

                heap->parray[index] = value;

                return true;

                }

                /***********************************************************

                * 下慮法實(shí)現(xiàn)數(shù)據(jù)的重排序操作

                * 實(shí)現(xiàn)的方式,將子結(jié)點(diǎn)的兩個(gè)兒子進(jìn)行比較tbw,將小的提升

                * 需要注意的是如何讓判斷節(jié)點(diǎn)是否一定存在右兒子

                * 實(shí)現(xiàn)的方式主要是利用了二叉堆的特性:

                * 2*pare = L_child

                * 2*pare + 1 = R_child;

                ***********************************************************/

                static void presort_BinaryHeap(BinaryHeap_handle_t heap,int hole)

                {

                /*這是二叉堆的特性*/

                int child = hole * 2;

                /*保存當(dāng)前數(shù)據(jù)操作*/

                int tmp = 0;

                assert(heap != NULL && heap->parray != NULL);

                tmp = heap->parray[hole];

                /*hold * 2 <= heap->currentSize 判斷了當(dāng)前結(jié)點(diǎn)是否為最低層*/

                for(; hole * 2 <= heap->currentSize; hole = child)

                {

                child = hole * 2;

                /*******************************

                *這句代碼解決是否存在右結(jié)點(diǎn)的問題

                *并確定了那個(gè)子結(jié)點(diǎn)提升的問題

                *******************************/

                if((child != heap->currentSize)

                && (heap->parray[child + 1] < heap->parray[child]))

                child ++;

                if(heap->parray[child] < tmp)

                {

                /*將子結(jié)點(diǎn)提升為父結(jié)點(diǎn)*/

                heap->parray[hole] = heap->parray[child];

                }

                }

                /*到達(dá)了最低的層,也就是樹葉*/

                heap->parray[hole] = tmp;

                }

                /*實(shí)現(xiàn)數(shù)據(jù)的下慮法實(shí)現(xiàn)數(shù)據(jù)的刪除操作*/

                int deleteMin(BinaryHeap_handle_t heap)

                {

                int ret = 0;

                int index = 0;

                assert(!isEmpty(heap));

                /*需要返回的值*/

                ret = heap->parray[1];

                /*將最后需要釋放內(nèi)存空間的值保存到第一個(gè)內(nèi)存空間中*/

                heap->parray[1] = heap->parray[heap->currentSize --];

                /*從表頭開始將新的二叉樹進(jìn)行重新排序*/

                presort_BinaryHeap(heap, 1);

                return ret;

                }

                測(cè)試代碼:

                #include "binaryheap.h"

                #include <stdio.h>

                #include <time.h>

                void print_binaryheap(BinaryHeap_handle_t heap)

                {

                int i = 0;

                assert(heap != NULL && heap->parray != NULL);

                for(i = 1; i <= heap->currentSize; ++ i)

                {

                if(i %6)

                printf("%d\t",heap->parray[i]);

                else

                printf("\n%d\t",heap->parray[i]);

                }

                printf("\n");

                }

                int main()

                {

                int i = 0;

                int value = 0;

                srand((int)time(0));

                printf("********Test Binaryheap**************\n");

                BinaryHeap_t bheap;

                BinaryHeap_handle_t *pheap = NULL;

                printf("init and alloc test:\n");

                if(init_BinaryHeap(&bheap,10))

                {

                printf("init_BinaryHeap() successed!\n");

                }

                if (alloc_BinaryHeap(&pheap,15));

                {

                printf("alloc_BInaryHeap() successed!\n");

                }

                printf("***insert test*****\n");

                for(; i < 10; ++ i)

                {

                if(!insert(&bheap,5 * i - rand()%20))

                {

                printf("i = %d:insert failed !!\n",i);

                }

                }

                for(i = 0; i < 15; ++ i)

                {

                if(!insert(pheap,i * 8 - rand()%20))

                {

                printf("i = %d:insert failed!!\n",i);

                }

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("****deleteMin test****\n");

                for(i = 0; i < 5; ++ i)

                {

                value = deleteMin(&bheap);

                printf("bheap deleted:%d\n",value);

                value = deleteMin(pheap);

                printf("pheap deleted:%d\n",value);

                }

                print_binaryheap(&bheap);

                print_binaryheap(pheap);

                printf("deleteMin test successed\n");

                printf("****delete and free test:*******\n");

                delete_BinaryHeap(&bheap);

                printf("Is the bheap empty ? %s\n",

                isEmpty(&bheap)?"Yes":"No");

                free_BinaryHeap(&pheap);

                printf("*********Test successed!***********\n");

                pheap = NULL;

                return 0;

                }

                測(cè)試結(jié)果:

                [gong@Gong-Computer c_binaryheap]$ ./testbinaryheap

                ********Test Binaryheap**************

                init and alloc test:

                init_BinaryHeap()

                alloc_BInaryHeap()

                ***insert test*****

                -11    -9    -9    14    15

                10    21    23    40    26

                -16    2    14    20    13

                21    33    49    61    67    76

                86    83    95    109

                ****deleteMin test****

                bheap deleted:-11

                pheap deleted:-16

                bheap deleted:-9

                pheap deleted:2

                bheap deleted:-9

                pheap deleted:13

                bheap deleted:10

                pheap deleted:14

                bheap deleted:14

                pheap deleted:20

                15    23    21    40    26

                21    49    21    61    67

                76    33    95    83    109

                deleteMin test successed

                ****delete and free test:*******

                Is the bheap empty ? Yes

                *********Test

                從上面的測(cè)試結(jié)果可知,基本上實(shí)現(xiàn)了二叉堆的基本插入、刪除操作。tbw代碼的關(guān)鍵點(diǎn)在于刪除中的下慮和插入過程中的上慮操作。以及如何判斷代碼是否存在右兒子,如何充分運(yùn)用二叉堆的特性。

            posted @ 2012-09-22 17:58 tbwshc 閱讀(341) | 評(píng)論 (0)編輯 收藏

             一,static和extern:
               
                大工程下我們會(huì)碰到很多源文檔。
               
                文檔a.c
               
                static int i; //只在a文檔中用
               
                int j;    //在工程里用
               
                static void init()         //只在a文檔中用
               
                {
               
                }
               
                void callme()          //在工程中用
               
                {
               
                static int sum;
               
                }
               
                上面的全局i變量和init()函數(shù)只能用在a.c文檔中,全局變量sum的作用域只在callme里。變量j和函數(shù)callme()的全局限擴(kuò)充到整個(gè)工程文檔。所以能夠在下面的b.c中用extern關(guān)鍵字調(diào)用。extern告訴編譯器這個(gè)變量或函數(shù)在其他文檔里已被定義了。
               
                文檔b.c
               
                extern int j;     //調(diào)用a文檔里的
               
                extern void callme();  //調(diào)用a文檔里的
               
                int main()
               
                {
               
                …
               
                }
               
                extern的另外用法是當(dāng)C和C++混合編程時(shí)假如c++調(diào)用的是c源文檔定義的函數(shù)或變量,那么要加extern來告訴編譯器用c方式命名函數(shù):
               
                文檔A.cpp調(diào)用a.c里面的變量i和函數(shù)callme()
               
                extern “C”  //在c++文檔里調(diào)用c文檔中的變量
               
                {
               
                int j;
               
                void callme();
               
                }
               
                int main()
               
                {
               
                callme();
               
                }
               
                二,static法則:
               
                A、若全局變量?jī)H在單個(gè)C文檔中訪問,則能夠?qū)⑦@個(gè)變量修改為靜態(tài)全局變量,tbw以降低模塊間的耦合度;
               
                B、若全局變量?jī)H由單個(gè)函數(shù)訪問,則能夠?qū)⑦@個(gè)變量改為該函數(shù)的靜態(tài)局部變量,以降低模塊間的耦合度;
               
                C、設(shè)計(jì)和使用訪問動(dòng)態(tài)全局變量、靜態(tài)全局變量、靜態(tài)局部變量的函數(shù)時(shí),需要考慮重入問題;
            posted @ 2012-09-22 17:56 tbwshc 閱讀(1419) | 評(píng)論 (0)編輯 收藏

                1、malloc函數(shù):向系統(tǒng)申請(qǐng)分配指定size個(gè)字節(jié)的內(nèi)存空間,分配成功后得到的是一個(gè)內(nèi)存塊,即連續(xù)的空間
               
                2、malloc分配不一定成功,所以最好驗(yàn)證一下:
               
                char *mallo;
               
                if ((mallo=(char *)malloc(36*sizeof(char)))==NULL)
               
                printf(“error in mallo!\n”);
               
                3、傳指針參數(shù)的原理在譚浩強(qiáng)書上已經(jīng)講過,這里只是做傳指針后實(shí)際的賦值方式探討
               
                傳遞過來的參數(shù):char *mallo
               
                3.1:mallo=“bag”;/*直接=不成功,調(diào)用后mallo只能在這個(gè)函數(shù)中打印出,調(diào)用這個(gè)函數(shù)的函數(shù)卻不能在調(diào)用后得到相應(yīng)的賦值結(jié)果*/
               
                3.2:for(;i<36;i++)
               
                {
               
                *(mallo++)='a'+rand()%26;
               
                //mallo[i]='a'+rand()%26;/*這句和上句的效果相同*/
               
                }/*for循環(huán)可以成功:依次賦值隨進(jìn)字母*/
               
                3.3:char *test=mallo;
               
                for(;i<36;i++)
               
                {
               
                *(test++)='a'+rand()%26;
               
                //test[i]='a'+rand()%26;
               
                }/*效果和3.2基本相同,只是讓思路更清晰的一種做法*/
               
                3.4:strcpy(mallo,“bag”);/*strcpy可以成功:strcpy會(huì)把“bag”中的三個(gè)字符和‘\0’一個(gè)一個(gè)的拷貝到mallo中,和上面的for循環(huán)類似*/
               
                一開始在Linux下這種方式并沒成功,在windows下添加#includes<string.h>后成功了(windows下沒有這個(gè)include會(huì)報(bào)錯(cuò)),再回到Linux下也能賦值成功,估計(jì)可能是沒有#includes<string.h>的緣故,但
               
                奇怪的是,我再去掉#includes<string.h>,還是成功,原因便無從知曉了。
               
                4、源碼
               
                #include <stdio.h>
               
                #include <stdlib.h>
               
                #include <string.h>
               
                #include <memory.h>
               
                /*接受傳過來的指針,并通過幾種方式賦值*/
               
                void memtest(char *mallo)
               
                {
               
                int i=0;
               
                //char *test=mallo;
               
                printf(“===============================================================”);
               
                //printf(“\n*mallo:%s\n”,*mallo);
               
                printf(“\nmallo: %s\n”,mallo);
               
                /*for(;i<36;i++)
               
                {
               
                *(mallo++)='a'+rand()%26;
               
                mallo[i]='a'+rand()%26;
               
                }*//*for循環(huán)可以成功*/
               
                strcpy(mallo,“bag”);/*strcpy可以成功*/
               
                //mallo=“bag”;/*直接=不成功*/
               
                //printf(“test:%s\n”,test);
               
                printf(“\n\”bug\“ ->mallo: %s\n”,mallo);
               
                }
               
                void main()
               
                {
               
                char *mallo;
               
                if ((mallo=(char *)malloc(36*sizeof(char)))==NULL)/*申請(qǐng)空間*/
               
                printf(“error in mallo!\n”);
               
                //memset(mallo,1,sizeof(mallo));
               
                //mallo=“shanghaimizhuan”;
               
                printf(“mallo_main: %s\n”,mallo);/*打印申請(qǐng)空間內(nèi)容,在windows下為亂碼,而Linux下不顯示*/
               
                /*以下打印數(shù)據(jù)在Linux和windows下數(shù)據(jù)不同,在賦值成功前windows已經(jīng)會(huì)檢測(cè)上面分配的空間大小,Linux則不會(huì):strlen(mallo)可以看出*/
               
                printf(“sizeof(mallo):%d--分割線--sizeof(*mallo):%d--分割線--strlen(mallo):%d\n”,sizeof(mallo),sizeof(*mallo),strlen(mallo));
               
                memtest(mallo);/*調(diào)用賦值函數(shù)*/
               
                printf(“===============================================================”);
               
                printf(“\nmallo_aftersetparam:%s\n”,mallo);/*tbw調(diào)用后輸出*/
               
                printf(“sizeof(mallo):%d--分割線--sizeof(*mallo):%d--分割線--strlen(mallo):%d\n”,sizeof(mallo),sizeof(*mallo),strlen(mallo));
               
                free(mallo);
               
                }
            posted @ 2012-09-16 14:10 tbwshc 閱讀(1598) | 評(píng)論 (1)編輯 收藏

                最近的幾次文章的評(píng)論中不少讀者提到文章的更新速度的更新量的問題,淺墨會(huì)逐漸重視起來,盡量在保證質(zhì)量的基礎(chǔ)上,每周都拿出夠分量的內(nèi)容。本周的文章算是近幾次更新量的一個(gè)彌補(bǔ),這篇文章的字?jǐn)?shù)達(dá)到了近一萬字。
               
                一、DirectX11的現(xiàn)有組件
               
                DirectX的API被分為頗多組件,每一組件都展現(xiàn)了系統(tǒng)不同方面的功能。其中的每一套API都能被獨(dú)立的使用,因此我們可以按照所需有選擇地自由添加我們游戲中需要的功能。在最新版本的DirectX中,不少組件迎來了更新,如Direct3D.其他的組件保持著現(xiàn)有的功能,當(dāng)然,也有一些被棄用的組件面臨著被移除的命運(yùn)。值得一提的是,DirectX中的各個(gè)內(nèi)部組件可以獨(dú)立進(jìn)行新功能的升級(jí)。
               
                下面進(jìn)行分別介紹:
               
                1.Direct2D
               
                Direct2D用于Win32應(yīng)用程序中2D圖形的繪制。Direct2D善于高性能矢量圖形的渲染。
               
                2. DirectWrite
               
                DirectWrite用于Direct2D應(yīng)用程序中的字體和文字渲染。
               
                3 . DXGI
               
                DXGI(DirectX Graphics Infrastructure)即DirectX圖形基礎(chǔ),用于
               
                Direct3D交換鏈(swap chains)和枚舉設(shè)備適配器(enumeration of deviceadapters)的創(chuàng)建。
               
                4 .Direct3D
               
                Direct3D用于DirectX中所有的與3D圖形相關(guān)的操作。Direct3D可謂DirectX中的大牌級(jí)API,受到了微軟最多的關(guān)懷與多次針對(duì)性的更新,它也最多被世人所熟知。這個(gè)專欄后續(xù)內(nèi)容的大部分的篇幅將集中于講解Direct3D上。
               
                5. XAudio2
               
                XAudio2 是一款底層的音頻處理API,以前為XDK(Xbox Development Kit)的一部分,目前,隸屬于DIRECTXSDK.XAudio2替換了DirectSound.初始版本的XAudio用于的第一代Xbox游戲機(jī)。
               
                6. XACT3
               
                XACT3是一款建立在XAudio2之上的更高級(jí)別的音頻處理API.XACT3允許開發(fā)者在他們的應(yīng)用中使用跨平臺(tái)音頻創(chuàng)作工具。若開發(fā)者希望從底層控制音頻系統(tǒng)或者希望創(chuàng)建自己的類型于XACT3的更高級(jí)別的音頻系統(tǒng),可以運(yùn)用XAdio2來完成各項(xiàng)功能。tbwXACT3,我們已經(jīng)在附錄B中討論過,作為“DIRECTX中的聲音”從配套網(wǎng)站,是一款非常容易上手的游戲音頻制作工具。
               
                7. XInput
               
                XInput是XDK和DirectX SDK的負(fù)責(zé)輸入功能的 API,用于處理Xbox 360控制器輸入。基本上任何可以在Xbox 360上可以使用的命令,都可以在PC上使用,而XInput就是幫助我們?cè)谶@些設(shè)備上進(jìn)行輸入相關(guān)操作的API.這些設(shè)備不僅包含Xbox手柄,也包含了其他很多設(shè)備。需要說明的是,XInput 替換了之前版本的DirectInput.
               
                注:XAudio是只能用于Xbox游戲機(jī)的音效API. XAudio2,其繼任者,可用于Xbox游戲機(jī)和基于Windows的PC.
               
                8 . XNAMath
               
                新出現(xiàn)的XNA Math 不是一款A(yù)PI,而是是一個(gè)數(shù)學(xué)庫(kù),進(jìn)行電子游戲中常見運(yùn)算的優(yōu)化工作。XNA Math采用了SIMD (Single Instruction Multiple Data單指令多數(shù)據(jù))來執(zhí)行多個(gè)操作的單指令調(diào)用。XNA Math庫(kù)適用于基于Windows的PC以及Xbox 360.相關(guān)內(nèi)容我們將在后續(xù)內(nèi)容繼續(xù)講解。
               
                注:XNA GameStudio為一款基于DirectX的游戲開發(fā)工具,可供我們使用C#和。NET編程語言來為Xbox360與Windows PC平臺(tái)編寫游戲。而XNA Math是一款DirectX SDK中數(shù)學(xué)庫(kù)的名字,可獨(dú)立于XNA Game Studio單獨(dú)使用。我們使用XNA Math不必下載XNA Game Studio SDK.


                
                9 . DirectCompute
               
                DirectCompute是一款DIRECTX 11中新加入的API,作用為支持GPU的通用多線程計(jì)算(general purpose multi threading computing)。GPU具有并行處理多任務(wù)的能力,如物理,視頻壓縮與視頻解壓,音頻處理等。并非所有的任務(wù)都適合GPU來完成,但是對(duì)于這些,由GPU來完成的可能性是巨大的(but for those that are, the possibilities are tremendous)。想了解DirectCompute的更多信息,可以查閱相關(guān)資料。
               
                10. DirectSetup
               
                當(dāng)我們完成游戲開發(fā)的時(shí)候,我們理所當(dāng)然地需要把完成品呈現(xiàn)給用戶。DirectSetup給我們提供了在用戶的電腦上安裝最新版本的DirectX的功能。DirectSetup也具有檢查已經(jīng)安裝了的DirectX版本號(hào)的功能。
               
                11.Windows Games Explorer
               
                WindowsGames Explorer(游戲資源管理器)是Windows Vista與Windows 7中的新特性,可供游戲開發(fā)者在他們的操作系統(tǒng)上展示(測(cè)試)他們的游戲。比如游戲的顯示,標(biāo)題,評(píng)級(jí),描述,特定區(qū)域的風(fēng)格框,評(píng)分內(nèi)容(如M為成人,T為青少年等),游戲數(shù)據(jù)統(tǒng)計(jì)和通知,家長(zhǎng)控制等。DirectX SDK中提供了大量如何使用自己的游戲的游戲資源管理器的教程,這對(duì)于發(fā)行一款游戲是非常有用的。下面的圖1是淺墨電腦上的Windows7游戲資源管理器的界面截圖

            posted @ 2012-09-16 14:09 tbwshc 閱讀(1868) | 評(píng)論 (1)編輯 收藏

            這里我們提出一種游戲循環(huán)的概念,游戲循環(huán)是將原先程序中的消息循環(huán)加以修改,方法是判斷其中的內(nèi)容目前是否有要處理的消息,如果有則進(jìn)行處理,否則按照設(shè)定的時(shí)間間隔來重繪畫面。下面是接下來一段游戲循環(huán)的程序代碼:
               
                //游戲循環(huán)
               
                while( msg.message!=WM_QUIT )               //注釋點(diǎn)1(詳細(xì)內(nèi)容見下)
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )       //注釋點(diǎn)2(詳細(xì)內(nèi)容見下)
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();                        //注釋點(diǎn)3
               
                if(tNow-tPre >= 100)                   //注釋點(diǎn)4
               
                MyPaint(hdc);
               
                }
               
                }
               
                我們來講解一下游戲循環(huán)片段中的幾個(gè)重點(diǎn)。
               
                <1>注釋點(diǎn)1:當(dāng)收到的msg.message不是窗口結(jié)束消息WM_QUIT,則繼續(xù)運(yùn)行循環(huán),其中msg是一個(gè)MSG的消息結(jié)構(gòu),其結(jié)構(gòu)成員message則是一個(gè)消息類型的代號(hào)。
               
                <2>注釋點(diǎn)2:使用PeekMessage()函數(shù)來檢測(cè)目前是否有需要處理的消息,若檢測(cè)到消息(包含WM_QUIT消息)則會(huì)返回一個(gè)非“0”值,否則返回“0”.因此在游戲循環(huán)中,若檢測(cè)到消息便進(jìn)行消息的處理,否則運(yùn)行else敘述之后的程序代碼。這里我們要注意的是,PeekMessage()函數(shù)不能用原先消息循環(huán)的條件GetMessage()取代,因?yàn)镚etMessage()函數(shù)只有在取得WM_QUIT消息時(shí)才會(huì)返回“0”,其他時(shí)候則是返回非“0”值或“-1”(發(fā)生錯(cuò)誤時(shí))
               
                <3>注釋點(diǎn)3:GetTickCount()函數(shù)會(huì)取得系統(tǒng)開始運(yùn)行到目前所經(jīng)過的時(shí)間,單位是毫秒(milliseconds)。  之前我理解錯(cuò)了,在這里感謝worldy的指出我的錯(cuò)誤。
               
                DWORD GetTickCount()    //取得系統(tǒng)開始到目前經(jīng)過的時(shí)間
               
                這里取得時(shí)間的目的主要是可以搭配接下來的判斷式,用來調(diào)整游戲運(yùn)行的速度,使得游戲不會(huì)因?yàn)檫\(yùn)行計(jì)算機(jī)速度的不同而跑得太快或者太慢。

                
                <4>注釋點(diǎn)4:if條件式中,“tPre”記錄前次繪圖的時(shí)間,而“tNow-tRre”則是計(jì)算上次繪圖到這次循環(huán)運(yùn)行之間相差多少時(shí)間。這里設(shè)置為若相差40個(gè)單位時(shí)間以上則再次進(jìn)行繪圖的操作,通過這個(gè)數(shù)值的控制可以調(diào)整游戲運(yùn)行的速度。這里設(shè)定40個(gè)單位時(shí)間(微秒)的原因是,因?yàn)槊扛?0個(gè)單位進(jìn)行一次繪圖的操作,那么1秒鐘大約重繪窗口1000/40=25次剛好可以達(dá)到期望值。
               
                由于循環(huán)的運(yùn)行速度遠(yuǎn)比定時(shí)器發(fā)出時(shí)間信號(hào)來得快,因此使用游戲循環(huán)可以更精準(zhǔn)地控制程序運(yùn)行速度并提高每秒鐘畫面重繪的次數(shù)。
               
                了解了游戲循環(huán)使用的基本概念之后,接下來的范例將以游戲循環(huán)的方法進(jìn)行窗口的連續(xù)貼圖,更精確地制作游戲動(dòng)畫效果。
               
                #include “stdafx.h”
               
                #include <stdio.h>
               
                //全局變量聲明
               
                HINSTANCE hInst;
               
                HBITMAP man[7];
               
                HDC  hdc,mdc;
               
                HWND    hWnd;
               
                DWORD   tPre,tNow,tCheck;                 //聲明三個(gè)函數(shù)來記錄時(shí)間,tPre記錄上一次繪圖的時(shí)間,tNow記錄此次準(zhǔn)備繪圖的時(shí)間,tCheck記錄每秒開始的時(shí)間
               
                int  num,frame,fps;                    //num用來記錄圖號(hào),frame用來累加每次畫面更新的次數(shù),fps(frame per second)用來記錄每秒畫面更新的次數(shù)
               
                //全局函數(shù)的聲明
               
                ATOM     MyRegisterClass
               
                (HINSTANCE hInstance);
               
                BOOL     InitInstance
               
                (HINSTANCE, int);
               
                LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM,
               
                LPARAM);
               
                void     MyPaint(HDC hdc);
               
                //***WinMain函數(shù),程序入口點(diǎn)函數(shù)**************************************
               
                int APIENTRY WinMain(HINSTANCE hInstance,
               
                HINSTANCE hPrevInstance,
               
                LPSTR     lpCmdLine,
               
                int       nCmdShow)
               
                {
               
                MSG msg;
               
                MyRegisterClass(hInstance);
               
                //運(yùn)行初始化函數(shù)
               
                if (!InitInstance (hInstance, nCmdShow))
               
                {
               
                return FALSE;
               
                }
               
                GetMessage(&msg,NULL,NULL,NULL);   //感謝xiaoxiangp的提醒,需要在進(jìn)入消息循環(huán)之前初始化msg,避免了死循環(huán)發(fā)生的可能性。
               
                //游戲循環(huán)
               
                while( msg.message!=WM_QUIT )
               
                {
               
                if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )
               
                {
               
                TranslateMessage( &msg );
               
                DispatchMessage( &msg );
               
                }
               
                else
               
                {
               
                tNow = GetTickCount();
               
                if(tNow-tPre >= 100)        //當(dāng)此次循環(huán)運(yùn)行與上次繪圖時(shí)間相差0.1秒時(shí)再進(jìn)行重繪操作
               
                MyPaint(hdc);
               
                }
               
                }
               
                return msg.wParam;
               
                }
               
                //****設(shè)計(jì)一個(gè)窗口類,類似填空題,使用窗口結(jié)構(gòu)體*************************
               
                ATOM MyRegisterClass(HINSTANCE hInstance)
               
                {
               
                WNDCLASSEX wcex;
               
                wcex.cbSize = sizeof(WNDCLASSEX);
               
                wcex.style   = CS_HREDRAW |
               
                CS_VREDRAW;
               
                wcex.lpfnWndProc    = (WNDPROC)WndProc;
               
                wcex.cbClsExtra  = 0;
               
                wcex.cbWndExtra  = 0;
               
                wcex.hInstance   = hInstance;
               
                wcex.hIcon   = NULL;
               
                wcex.hCursor     = NULL;
               
                wcex.hCursor     = LoadCursor(NULL,
               
                IDC_ARROW);
               
                wcex.hbrBackground  = (HBRUSH)
               
                (COLOR_WINDOW+1);
               
                wcex.lpszMenuName   = NULL;
               
                wcex.lpszClassName  = “canvas”;
               
                wcex.hIconSm     = NULL;
               
                return RegisterClassEx(&wcex);
               
                }
               
                //****初始化函數(shù)*************************************
               
                // 從文件加載位圖
               
                BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
               
                {
               
                char filename[20] = “”;
               
                int i;
               
                hInst = hInstance;
               
                hWnd = CreateWindow(“canvas”, “動(dòng)畫演示” ,
               
                WS_OVERLAPPEDWINDOW,
               
                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
               
                NULL, NULL, hInstance, NULL);
               
                if (!hWnd)
               
                {
               
                return FALSE;
               
                }
               
                MoveWindow(hWnd,10,10,600,450,true);
               
                ShowWindow(hWnd, nCmdShow);
               
                UpdateWindow(hWnd);
               
                hdc = GetDC(hWnd);
               
                mdc = CreateCompatibleDC(hdc);
               
                //載入各個(gè)人物位圖
               
                for(i=0;i<7;i++)
               
                {
               
                sprintf(filename,“man%d.bmp”,i);
               
                man[i] = (HBITMAP)LoadImage
               
                (NULL,filename,IMAGE_BITMAP,640,480,LR_LOADFROMFILE);
               
                }
               
                num = 0;
               
                frame = 0;
               
                MyPaint(hdc);
               
                return TRUE;
               
                }
               
                //****自定義繪圖函數(shù)*********************************
               
                // 1.計(jì)算與顯示每秒畫面更新次數(shù)
               
                // 2.按照?qǐng)D號(hào)順序進(jìn)行窗口貼圖
               
                void MyPaint(HDC hdc)
               
                {
               
                char str[40] = “”;
               
                if(num == 7)
               
                num = 0;
               
                frame++;            //畫面更新次數(shù)加1
               
                if(tNow - tCheck >= 1000)               //tbw判斷此次繪圖時(shí)間由前一秒算起是否已經(jīng)達(dá)到1秒鐘的時(shí)間間隔。若是,則將目前的‘frame’值賦給“fps”,表示這一秒內(nèi)所更新的畫面次數(shù),然后將“frame”值回0,并重設(shè)下次計(jì)算每秒畫面數(shù)的起始時(shí)間“iCheck”.
               
                {
               
                fps = frame;
               
                frame = 0;
               
                tCheck = tNow;
               
                }
               
                SelectObject(mdc,man[num]);         //選用要更新的圖案到mdc中,再輸出顯示每秒畫面更新次數(shù)的字符串到mdc上,最后將mdc的內(nèi)容貼到窗口中。
               
                sprintf(str,“每秒顯示 %d個(gè)畫面”,fps);
               
                TextOut(mdc,0,0,str,strlen(str));
               
                BitBlt(hdc,0,0,600,450,mdc,0,0,SRCCOPY);
               
                tPre = GetTickCount();     //記錄此次繪圖時(shí)間,供下次游戲循環(huán)中判斷是否已經(jīng)達(dá)到畫面更新操作設(shè)定的時(shí)間間隔。
               
                num++;
               
                }
               
                //******消息處理函數(shù)*********************************
               
                LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
               
                WPARAM wParam, LPARAM lParam)
               
                {
               
                int i;
               
                switch (message)
               
                {
               
                case WM_DESTROY:     //窗口結(jié)束消息
               
                DeleteDC(mdc);
               
                for(i=0;i<7;i++)
               
                DeleteObject(man[i]);
               
                ReleaseDC(hWnd,hdc);
               
                PostQuitMessage(0);
               
                break;
               
                default:     //其他消息
               
                return DefWindowProc(hWnd,
               
                message, wParam, lParam);
               
                }
               
                return 0;
               
                }
               
                程序的運(yùn)行結(jié)果如下圖:
            posted @ 2012-09-16 14:07 tbwshc 閱讀(116) | 評(píng)論 (0)編輯 收藏

            PB9開發(fā)的程序,用PB11.5打開過后,再用PB9就打不開了
            PB9開發(fā)的程序,用PB11.5打開過后,再用PB9就打不開了,添加目標(biāo)時(shí)提示 could not add target because of a bad application library in "g:\11\tv_prg.pbt",怎辦才能用PB9重新打開呢?

            ------解決方案--------------------------------------------------------
            這個(gè)恐怕不行了。
            那個(gè)項(xiàng)目已經(jīng)被遷移成了 PB11.5 的版本了。

            像這樣的操作應(yīng)該事件tb做備份的。
            ------解決方案--------------------------------------------------------
            高的能兼容低的,低的不能兼容高的
            ------解決方案--------------------------------------------------------
            如果你沒有備份的話 那你悲劇了
            ------解決方案--------------------------------------------------------
            找一以前的備份,用備份吧

            如果沒有備份,你真的悲劇了
            ------解決方案--------------------------------------------------------
            試試 Regenerate
            posted @ 2012-09-08 13:34 tbwshc| 編輯 收藏

            僅列出標(biāo)題
            共10頁: 1 2 3 4 5 6 7 8 9 Last 
            久久精品无码一区二区三区日韩| 久久久久av无码免费网| 久久国产影院| 中文字幕人妻色偷偷久久| 国内精品久久久久影院一蜜桃| 99久久精品免费国产大片| 亚洲人成无码www久久久| 国产美女久久精品香蕉69| 精品国产综合区久久久久久| 中文无码久久精品| 精品国产青草久久久久福利| 久久久久久久亚洲Av无码| 亚洲国产成人久久综合区| 久久夜色精品国产亚洲| 99久久精品国产一区二区| 99精品伊人久久久大香线蕉| 久久综合噜噜激激的五月天| 国产精品欧美久久久久天天影视| 中文字幕久久精品无码| 无码任你躁久久久久久老妇| 久久亚洲精品中文字幕三区| 久久人妻无码中文字幕| 日韩十八禁一区二区久久| 精品久久一区二区三区| 午夜精品久久久久久99热| 伊人久久大香线蕉综合5g| 久久国产三级无码一区二区| 久久久久久综合一区中文字幕| 日韩人妻无码一区二区三区久久 | 久久亚洲国产午夜精品理论片| 国内精品九九久久精品| 亚洲国产成人久久综合野外| 精品无码久久久久久国产| 色综合久久88色综合天天| 国产日产久久高清欧美一区| 亚洲午夜久久久久久噜噜噜| 久久精品无码一区二区WWW| 中文字幕精品久久久久人妻| 久久亚洲精品国产精品婷婷| 亚洲v国产v天堂a无码久久| 亚洲欧美日韩精品久久亚洲区|