20160207.CCPP體系詳解(0017天)

尹成發表於2016-02-18

程式片段:01.Point.c+02.程式.c+03.記憶體的棧和堆.c
內容概要:記憶體32位和64位的區別

///01.Point.c
#include <stdio.h>
#include <stdlib.h>

//01.指標變數所佔用的記憶體尺寸由編譯器進行直接決定
//      指標變數所佔用的記憶體尺寸同時直接或間接與CPU-->作業系統-->編譯器平臺有關
//          綜合決定:CPU-->作業系統-->編譯器平臺
//          直接決定:編譯器平臺
//02.指標變數當中的指標就是記憶體定址範圍當中的地址(注意型別差別)
//  32位作業系統的CPU定址能力
//      32位編譯器:0x00000000~0xFFFFFFFF
//          2^32=2^2*2^10*2^10*2^10=4*1024*1024*1024=4G
//  64位作業系統的CPU定址能力
//      64位編譯器:0x0000000000000000~0xFFFFFFFFFFFFFFFFF
//          所能定址的範圍很大
//03.CPU的不同位數所導致的能力差異:
//  1.定址能力不同:
//      定址範圍非常的大
//  2.運算能力不同:
//      32位CPU只能做32位運算;
//      64位CPU既能做32位運算,也能做64位運算
int main01(void)
{
    int num = 1;
    int * pNum = &num; 
    printf("%llu \n", sizeof(pNum));

    system("pause");
}

//04.暫存器相關的特點分析:
//  1.所有的運算操作都需要藉助CPU的暫存器區域進行完成
//  2.任何一個表示式都是位於CPU的暫存器區域(eax|rax)
//      但是C語言不能直接對CPU的暫存器進行寫入操作,除非內嵌彙編
//      注:包括對任何一個變數名的取地址操作(&varName)
//05.計算機在CPU的暫存器區域生成常量的過程:
//      CPU-->暫存器-->程式碼區-->符號表-->讀取常量-->暫存器生成常量
int main02(void)
{
    int num = 1;
    int data = 0;
    data = num;
    //&(num+1);
    data = num + 1;
    data = num + 2;

    system("pause");
}
///02.程式.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

//01.單個程式處於不同編譯器平臺之下所支援的單程式記憶體尺寸不同:
//  32位編譯器平臺情況之下,所支援的單程式最大記憶體尺寸為2GB
//  64位編譯器平臺情況之下,所指吃的單程式最大記憶體尺寸為1024GB
//  注:
//      1.區分大小寫B的區別
//      2.該單程式記憶體尺寸指整個程式所佔用的記憶體(包含:程式碼區+全域性區+棧記憶體+堆記憶體)
//      3.單個程式所佔用的記憶體尺寸是由編譯器平臺的位數所直接決定的(間接因素:CPU->作業系統->編譯器)
//02.記憶體分配,記憶體釋放,記憶體回收四個詞語的意思:
//  記憶體分配:作業系統為程式分配指定記憶體區域的訪問許可權(寫入許可權和讀取許可權)
//  記憶體釋放:作業系統從程式回收指定記憶體區域的訪問許可權
//      只是收回許可權,不會清空資料
//  記憶體回收:清空記憶體的實際資料
//      不僅收回許可權,還會清空資料
//03.關於軟訪問和硬訪問的區別:
//  軟訪問:所能訪問的最小記憶體單位是二進位制位(Bit)(補碼)
//      但是通常都是採取位元組作為最小單位操作記憶體的
//      除非是位運算就會操作到記憶體的最小單位
//  硬訪問:所能訪問的最小硬碟單位是位元組(Byte)
int main03(void)
{
    while (1)
    {
        malloc(1024*1024*100);//不斷的分配記憶體空間
        Sleep(100);
    }

    system("pause");
}
///03.記憶體的棧和堆.c
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <process.h>

//01.最常用棧記憶體和堆記憶體耗費方式:
//  棧耗費:auto int num
//  對耗費:malloc(1024)
//02.棧記憶體和堆記憶體的基本特點:
//  資料結構的棧和堆:
//      棧:先進後出的一種資料結構
//      堆:一種二叉樹形式的儲存結構
//  記憶體訪問的棧記憶體和堆記憶體:
//      棧記憶體:自動釋放,自動回收
//      堆記憶體:手動釋放,手動回收
//  注:棧記憶體由編譯器進行維護,編譯器控制自動釋放和自動回收的時機,預設棧記憶體所佔用的尺寸為1M,可以手動擴充編譯器
//      所操控的棧記憶體尺寸大小,通過專案配置修改棧記憶體所操縱的棧記憶體尺寸大小[配置屬性-->連結器-->系統-->堆疊保留大小]
//03.區分虛擬記憶體和實體記憶體:
//  虛擬記憶體:硬碟記憶體
//  實體記憶體:真實記憶體
void stack(int numA)//int numA:作為形式引數,佔用棧記憶體
{
    int numB = 10;//區域性變數,佔用棧記憶體
    printf("%p, %p \n", &numA, &numB);
    numA = 1;
    numB = 2;
    getchar();//某些情況之下如果不能進行斷點除錯,需要新增上這句無用的程式碼,以便插上斷點進行斷點除錯
}

//04.關於編譯器的自動優化特點解釋:
//  1.一個函式在呼叫完成之後,如果呼叫了其它函式,那麼當前函式會被立即釋放
//  2.然而編譯器檢測到兩次呼叫的是相同函式,只不過中間插入了一個無關緊要的函式,
//      那麼此時的編譯器不會對兩次重複呼叫的相同函式進行不同的棧記憶體開闢
//05.靜態陣列分配的程式碼分析:
//  int intArr[1024*1024];
//      1.該陣列佔用棧記憶體位元組數為4M
//      2.該陣列屬於靜態陣列,需要在程式碼一旦加入進記憶體之後就決定該陣列的記憶體尺寸
//      3.該陣列分配方式為靜態分配,因此必須使用常量指明陣列元素個數
int main04(void)
{
    //stack(1);
    //printf("\n\n\n");
    //stack(1);
    //printf("\n\n\n");
    //int intArr[1024 * 1024];
    system("pause");
}

//06.執行緒任務函式的標準格式
void run(void * p)
{
    while (1)
    {
        int num[1024 * 1024];//自動釋放回收棧記憶體
    }

    while (1)
    {
        malloc(1024 * 1024 * 10);//不斷的進行堆記憶體的分配而沒有進行釋放,很容易造成記憶體溢位情況
        Sleep(1000);//堆記憶體膨脹-->導致整個程式的記憶體溢位,不是棧記憶體溢位
    }
}

//07.32位編譯器平臺之下,由於編譯器所編譯的單個程式程式所支援的最大記憶體尺度為2GB(同時包含記憶體四區)大小
//  全域性區+程式碼區+棧記憶體+堆記憶體=2GB,因此堆記憶體所佔用的尺寸極限必定小於2GB
//08.關於多執行緒情況之下的單個程式的記憶體使用情況:
//  1.多條執行緒共享同一個程式的堆記憶體
//  2.各條執行緒獨自佔用一定的程式的棧記憶體
//09.關於啟動執行緒函式處理執行緒任務程式碼的特點分析:
//  程式碼:_beginthread(taskFun, 0, NULL);
//  引數說明:
//          taskFun:執行緒待處理的任務函式
//                     0:以跟主執行緒相同棧記憶體尺寸分配執行緒任務棧記憶體-->通常所說的堆疊保留大小其實就是主執行緒的堆疊保留大小
//              NULL:傳遞給任務處理函式的實際引數
int main05(void)
{
    //void * p = malloc(1024 * 1024);//分配1M
    for (int i = 0; i < 8; ++i)
    {
        _beginthread(run, 0, NULL);//多執行緒,每一個執行緒都有各自獨立的棧記憶體
    }

    system("pause");
}

程式片段(02):01.Heap.c
內容概要:Heap

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <process.h>

void taskFun(void * p)
{
    while (1)
    {
        malloc(1024 * 1024 * 10);
        Sleep(100);
    }
}

int main01(void)
{
    //taskFun(NULL);    

    for (int i = 0; i < 3; ++i)
    {
        _beginthread(taskFun, 0, NULL);
    }

    system("pause");
}

程式片段(03):stack.h+stack.c+main.c
內容概要:Stack

///stack.h
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define EN 100
struct stack//單個結構體變數可以用於整合多個不同型別的變數
{
    int data[EN];//棧記憶體空間
    int top;//棧頂標識
};

typedef struct stack Stack;//Stack別名
void initStack(Stack * pStack);//初始化棧結構
int isEmpty(Stack * pStack);//判斷棧結構是否為空
int isFull(Stack * pStack);//判斷棧結構是否填滿
void pushStack(Stack * pStack, int value);//棧結構壓入資料
int popStack(Stack * pStack);//棧結構彈出資料
int getTop(Stack * pStack);//獲取棧頂資料
void showStack(Stack * pStack);//棧結構顯示
///stack.c
#include "stack.h"

void initStack(Stack * pStack)
{
    memset(pStack->data, 0, sizeof(int)*EN);//資料清零,模擬回收資料
    pStack->top = -1;//表示棧頂索引只要在0以上就表示棧結構當中儲存有資料
}

int isEmpty(Stack * pStack)
{
    if (-1 == pStack->top)
    {
        return 1;
    }
    return 0;
}

int isFull(Stack * pStack)
{
    if (EN - 1 == pStack->top)
    {
        return 1;
    }
    return 0;
}

void pushStack(Stack * pStack, int value)
{
    if (1 == isFull(pStack))
    {
        return;
    }
    pStack->data[++pStack->top] = value;
}

int popStack(Stack * pStack)
{
    if (1 == isEmpty(pStack))
    {
        return;
    }
    return pStack->data[pStack->top--];
}

int getTop(Stack * pStack)
{
    if (1 == isFull(pStack))
    {
        return -1;
    }

    return popStack(pStack);
}

void showStack(Stack * pStack)
{
    if (1 == isEmpty(pStack))
    {
        return;
    }
    printf("棧結構的資料是: \n");
    for (int i = 0; i <= pStack->top; ++i)
    {
        printf("%4d \n", pStack->data[i]);
    }
    printf("\n");
}
///main.c
#define _CRT_SECURE_NO_WARNINGS
#include "stack.h"

//01.結構體型別與結構體變數:
//  1.結構體型別:用於整合多個不同型別
//  2.結構體變數:用於整合多個不同型別的變數
//  3.結構體變數的成員訪問方式:點訪問符+指標訪問符
//      注:點號(".")操作符的優先順序大於星號("*")操作符的優先順序
int main01(void)
{
    struct MyStack//結構體型別用於整合多個不同型別
    {
        int data[10];
        int top;
    };
    //結構體變數意義:整合多個不同型別的變數
    struct MyStack my1 = { { 1, 2, 3 }, 1 };//結構體變數的靜態初始化
    printf("%d \n", my1.top);//訪問結構體變數的成員變數
    printf("%d \n", (&my1)->top);
    printf("%d \n", my1.top);
    printf("%d \n", (*(&my1)).top);

    struct MyStack * my2 = &my1;
    //printf("%d \n", *my2.top);//星號("*")的優先順序低於點號(".")
    printf("%d \n", (*my2).top);

    for (int i = 0; i < 10; ++i)
    {
        printf("%d \n", my1.data[i]);//可以用點號(".")操作符進行訪問
    }

    system("pause");
}

int main02(void)
{
    //int intArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    Stack myStack;
    initStack(&myStack);
    for (int i = 0; i < 10; ++i)
    {
        pushStack(&myStack, i);
    }
    while (!isEmpty(&myStack))
    {
        printf("%3d", getTop(&myStack));
    }

    system("pause");
}

int main03(void)
{
    //int intArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    Stack myStack;
    initStack(&myStack);
    for (int i = 0; i < 10; ++i)
    {
        pushStack(&myStack, i);//壓棧一個
        printf("%3d", getTop(&myStack));//彈棧一個
    }

    system("pause");
}

//02.如何求取一個整數的二進位制形式?
//  10      %2      5       0
//    5     %2      2       1
//    2     %2      1       0
//    1     %2      0       1
//    0     %2      0       0-->直到被除數為0,末尾新增一個0(被除數:0->取模數:0)
void    intHexToBin(int intHexNum)
{
    if (0 == intHexNum)//表示最終的被除數為0的情況
    {
        putchar('0');//表明確實已經除到了最後一個數值-->意思:直到被除數為0,末尾新增了一個0
    }
    else
    {
        intHexToBin(intHexNum / 2);
        putchar('0' + intHexNum % 2);//十進位制的整數型別轉化為字元型的整數
    }
}

int main04(void)
{
    int intHexNum = 0;
    scanf("%d", &intHexNum);
    intHexToBin(intHexNum);

    system("pause");
}

//壓入一個,彈出一個
int main05(void)
{
    int intNum;
    scanf("%d", &intNum);
    Stack myStack;
    initStack(&myStack);
    while (intNum)
    {
        pushStack(&myStack, intNum % 2);
        putchar('0' + getTop(&myStack));
        intNum /= 2;
    }
    putchar('0');//當被除數變為0的時候,也需要在末尾進行補零操作

    system("pause");
}

//壓入全部,一次性逆序彈出
int main06(void)
{
    int num;
    scanf("%d", &num);
    Stack myStack;
    initStack(&myStack);
    while (num)
    {
        pushStack(&myStack, num % 2);
        num /= 2;
    }
    pushStack(&myStack, 0);//當被除數為0的時候,需要補上一個儲存0

    while (!isEmpty(&myStack))
    {
        putchar('0' + getTop(&myStack));
    }

    system("pause");
}

程式片段(04):01.蟒蛇.c
內容概要:

#include <stdio.h>
#include <stdlib.h>

//01.蛇形行走:
//  1.規律總結:
//      (1).每次都是圍繞"未走過"的"最外圈"棋盤
//      (2).每一圈兒的行走起點都是該圈兒的最左上角
//  2.必殺技巧:
//      (1).二維陣列模擬棋盤
//      (2).採用迴圈變數控制圈兒數以及轉向(四個方向)
//  注:圈數採用變數模擬和控制
//02.控制技巧:
//  1.外層迴圈核心控制圈數
//      (1).圈數必定大於等於1
//      (2).圈數與行數之間的關係
//          行數=1-->圈數=1
//          行數=2-->圈數=1
//          規律:(行數+1)/2-->圈數
//  2.內部迴圈控制四周的轉向操作
//      在這裡是順時針的轉向操作
//  3.空置棋盤,填充規律數字
#define N 10
int intArrArr[N][N] = { 0 };
int main01(void)
{
    int num = 1;//規律數值生成器:初始化為1
    for (int q = 0, x = 0, y = 0; q < (N + 1) / 2; ++q)
    {
        while (y < N - q)//控制橫向列數
        {
            intArrArr[x][y] = num++;
            ++y;
        }
        --y;//回列
        ++x;//走行
        while (x < N - q)//控制縱向行數
        {
            intArrArr[x][y] = num++;
            ++x;
        }
        --x;//回行
        --y;//走列
        while (y > q - 1)
        {
            intArrArr[x][y] = num++;
            --y;
        }
        ++y;//回列
        --x;//走行
        while(x > q)
        {
            intArrArr[x][y] = num++;
            --x;
        }
        ++x;//回行
        ++y;//走列
    }

    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            printf("%4d", intArrArr[i][j]);
        }
        printf("\n");
    }

    system("pause");
}

程式片段(05):陣列交集與並集.c
內容概要:交集與並集

#include <stdio.h>
#include <stdlib.h>

//00.求交併集的首要條件是:
//  去除各個集合當中重複的元素,防止重複儲存
#define M 15
#define N 10
//01.求交集規律總結:
//  1.新建交集陣列儲存交集結果:
//      交集陣列的元素個數最多為較小待求交集的那個陣列的元素個數
//  2.以待求交集的那個陣列的元素個數為外層迴圈遍歷該陣列
//      然後用該資料與另外一個較大待求交集的那個陣列元素進行比較
//  3.如果較小陣列元素和較大陣列元素一樣
//      那就將該陣列元素存入進交集陣列當中,否則不用放入
int main01(void)
{
    int intArrM[M] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    int intArrN[N] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

    int intArrJiao[N] = { 0 };//求交集
    int index = 0;
    int flag = 0;
    for (int i = 0; i < N; ++i)//外層迴圈最少,能夠達到最大的節省迴圈次數
    {
        flag = 0;
        for (int j = 0; j < M; ++j)
        {
            if (intArrN[i] == intArrM[j])
            {
                flag = 1;
                break;
            }
        }
        if (1 == flag)
        {
            intArrJiao[index++] = intArrN[i];
        }
    }
    for (int i = 0; i < N; ++i)
    {
        if (0 == intArrJiao[i])
        {
            break;
        }
        printf("%3d", intArrJiao[i]);
    }

    system("pause");
}

//02.求並集規律總結:
//  1.新建並集陣列儲存並集結果:
//      並集陣列的元素個數最多為兩個待求並集陣列的元素個數總和
//  2.並集陣列拷貝:
//      將待求並集陣列當中元素最多的那個陣列的元素全部拷貝到並集陣列當中
//      因為並集陣列當中元素最少就是較大的那個陣列當中的元素個數
//  3.然後遍歷較小的那個待求並集陣列當中的每個元素
//      再用該元素與較大的那個待求並集陣列的元素進行比對
//  4.如果較小陣列元素和較大陣列元素不一樣
//      那就將該陣列元素儲存進並集陣列當中,否則不用進行存入
int main02(void)
{
    int intArrM[M] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    int intArrN[N] = { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

    int intArrBing[M + N] = { 0 };
    for (int i = 0; i < M; ++i)
    {
        intArrBing[i] = intArrM[i];
    }
    int index = M;
    int flag = 0;
    for (int i = 0; i < N; ++i)
    {
        flag = 0;
        for (int j = 0; j < M; ++j)
        {
            if (intArrN[i] == intArrM[j])
            {
                flag = 1;
                break;
            }
        }
        if (0 == flag)
        {
            intArrBing[index++] = intArrN[i];
        }
    }
    for (int i = 0; i < M + N; ++i)
    {
        if (0 == intArrBing[i])
        {
            break;
        }
        printf("%3d", intArrBing[i]);
    }

    system("pause");
}

程式片段(06):01.破解密碼.c
內容概要:密碼概率分佈

#include <stdio.h>
#include <stdlib.h>

#define N 20
int intArr[N] = { 1, 2, 3, 1, 2, 9, 9, 10, 11, 12, 1, 2, 1, 2, 2, 2, 1, 10, 11, 98 };
typedef struct
{
    int value;//密碼值
    int count;//次數
} Pass;
Pass pass[N] = { 0 };//結構體資料清零

int main(void)
{
    //對陣列pass當中的元素進行排序
    int currentIndex = 0;
    int currentValue = 0;
    for (int i = 1; i < N; ++i)
    {
        currentIndex = i;
        currentValue = intArr[i];
        while (currentIndex > 0 && intArr[currentIndex - 1] > currentValue)
        {
            intArr[currentIndex] = intArr[currentIndex - 1];
            --currentIndex;
        }
        intArr[currentIndex] = currentValue;
    }

    for (int i = 0; i < N; ++i)
    {
        printf("%3d", intArr[i]);
    }
    printf("\n\n");

    int index = 0;//代表結構體陣列當中第一個結構體元素的索引
    int count = 0;
    for (int i = 0; i < N; ++i)
    {   
        count = 1;
        pass[index].value = intArr[i];
        for (int j = i; j < N - 1; ++j)
        {
            if (intArr[j] == intArr[j + 1])
            {
                ++count;
            }
            else
            {
                i = j;//最後一個相同值的所在位置
                break;//中斷
            }
        }
        pass[index++].count = count;
    }

    //for (int i = 0; i < N; ++i)
    //{
    //  if (0 == pass[i].count)
    //  {
    //      break;
    //  }
    //  printf("%3d%3d \n",pass[i].value, pass[i].count);
    //}

    int end = 0;
    for (int i = 0; i < N; ++i)
    {
        if (pass[i].count == 0)
        {
            end = i;//等效於有效元素個數
        }
    }

    int maxIndex = 0;
    int maxCount = 0;
    for (int i = 0; i < end - 1; ++i)
    {
        maxIndex = i;
        maxCount = pass[i].count;
        for (int j = i + 1; j < end; ++j)
        {
            if (maxCount < pass[j].count)
            {
                maxIndex = j;
                maxCount = pass[j].count;
            }
        }
        if (i != maxIndex)
        {
            pass[i].value = pass[i].value ^ pass[maxIndex].value;
            pass[maxIndex].value = pass[i].value ^ pass[maxIndex].value;
            pass[i].value = pass[i].value ^ pass[maxIndex].value;

            pass[i].count = pass[i].count ^ pass[maxIndex].count;
            pass[maxIndex].count = pass[i].count ^ pass[maxIndex].count;
            pass[i].count = pass[i].count ^ pass[maxIndex].count;
        }
    }
    for (int i = 0; i < end; ++i)
    {
        if (0 == pass[i].count)
        {
            break;
        }
        printf("%3d%3d \n", pass[i].value, pass[i].count);
    }

    system("pause");
}

程式片段(07):stack.h+stack.c+01.臺階.c
內容概要:臺階問題

///stack.h
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define N 100
struct stack
{//[將結構體當中為一個整體進行看待]
    int data[N];
    int top;//標識棧頂
};
typedef struct stack Stack;//Stack作為該結構體的別名,相當於是對重新定義的一個資料型別進行更名識別

//[對結構體當中的某個屬性進行修改]
void init(Stack *p);//初始化
int isempty(Stack *p);//判斷棧是否為空
int isfull(Stack *p);//判斷棧溢位
int gettop(Stack *p);//獲取棧頂
void push(Stack *p);//插入資料 
void pop(Stack *p);//吐出棧頂資料
void show(Stack *p);//顯示棧結構資料
///stack.c
#include "stack.h"

void init(Stack *p)//初始化棧結構
{
    memset(p->data, 0, sizeof(int)*N);//資料清零
    p->top = -1;//代表為空
}
int isempty(Stack *p)//判斷棧結構是否為空
{
    if (p->top=-1)
    {
        return 1;//為空
    }
    else
    {
        return 0;//不為空
    }
}
int isfull(Stack *p)//判斷棧溢位
{
    if (p->top==N-1)
    {
        return 1;//溢位
    }
    else
    {
        return 0;//還能再喝點兒
    }
}
int gettop(Stack *p)//獲取棧頂資料
{
    return p->data[p->top];
}
void push(Stack *p, int key)//將資料壓入棧頭
{
    if (isfull(p)==1)
    {
        return;
    }
    else
    {
        p->top += 1;//結構體指向下一個整體
        p->data[p->top] = key;//壓入資料
    }
}
void pop(Stack *p)//吐出
{
    if (isempty(p)==1)
    {
        return; 
    }
    else
    {
        p->top -= 1;//出棧
    }
}
void show(Stack *p)//顯示棧結構當中的所有資料
{
    if (isempty(p)==1)
    {
        return;
    }
    else
    {
        printf("\n棧的資料時\n");
        for (int i = 0; i <=p->top; i++)
        {
            printf("%4d", p->data[i]);//列印棧結構當中的資料
        }
        printf("\n");
    }
}
///01.臺階.c
#include "stack.h"

#define STPES 10
//01.三級臺階問題:
//  1.1次只能走1步,2步,或者3步
//  2.10級臺階有多少中走法?
//  1       1
//  2       2       11+2
//  3       4       111+12+21+3
//  4       7       1111    +112+121+211+13+31
//  n=(n-3)+(n-2)+(n-1);//規律總結
int stepMethods(int steps)
{
    if (1 == steps)
    {
        return 1;
    }
    else if (2 == steps)
    {
        return 2;
    }
    else if (3 == steps)
    {
        return 4;
    }
    return stepMethods(steps - 3) + stepMethods(steps - 2) + stepMethods(steps - 1);
}

//01.通過陣列棧來提升遞迴效率:
//  遞迴-->加速-->迴圈+陣列棧
int main01(void)
{
    int intArr[STPES] = { 1, 2, 4 };//前3級臺階作為基礎進行規律的建立
    for (int i = 3; i < STPES; ++i)
    {
        intArr[i] = intArr[i - 3] + intArr[i - 2] + intArr[i - 1];
    }
    printf("stepMethods = %d, intArr[N - 1] = %d \n", stepMethods(STPES), intArr[STPES - 1]);

    system("pause");
}

//02.直接迴圈結構
int main02(void)
{
    int steps1 = 1;
    int steps2 = 2;
    int steps3 = 4;
    int stepsN = 0;
    for (int i = 3; i < 10; ++i)
    {
        stepsN = steps1 + steps2 + steps3;
        steps1 = steps2;
        steps2 = steps3;
        steps3 = stepsN;
    }
    printf("stepsN = %d \n", stepsN);

    system("pause");
}

程式片段(08):queue.h+queue.c+01.佇列.c
內容概要:佇列

///queue.h
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define N 100//佇列結構的元素實體個數
typedef struct
{
    int data[N];//佇列結構的記憶體儲存空間
    int head;//標識佇列結構的頭部位置
    int back;//標識佇列結構的尾部位置
} Queue;

void initQueue(Queue * pQueue);//初始化佇列結構
int isEmpty(Queue * pQueue);//判定佇列結構是否為空
int isFull(Queue * pQueue);//判定佇列結構是否已滿
void enQueue(Queue * pQueue, int value);//為佇列結構新增一個資料元素
void deQueue(Queue * pQueue);//出隊
int getLast(Queue * pQueue);//獲取佇列尾部資料實體
void showQueue(Queue * pQueue);//展示佇列狀態
///queue.c
#include "queue.h"

//01.佇列結構的開頭位置是固定死的
void initQueue(Queue * pQueue)
{
    (*pQueue).head = (*pQueue).back = 0;//標識佇列結構為空
    memset(pQueue, 0, sizeof(int)*N);//只是針對於記憶體空間的資料清零操作
}

int isEmpty(Queue * pQueue)
{
    if ((*pQueue).head == (*pQueue).back)
    {
        return 1;
    }
    return 0;
}

int isFull(Queue * pQueue)
{
    if (pQueue->back == N - 1)
    {
        return 1;
    }
    return 0;
}

void enQueue(Queue * pQueue, int value)
{
    if (1 == isFull(pQueue))
    {
        return;
    }
    else
    {
        if (1 == isEmpty(pQueue))
        {
            (*pQueue).data[0] = value;
            ++((*pQueue).back);
        }
        else
        {
            for (int i = (*pQueue).back; i > 0; --i)
            {
                (*pQueue).data[i] = (*pQueue).data[i - 1];
            }
            (*pQueue).data[0] = value;
            ++((*pQueue).back);
        }
    }
}

int getLast(Queue * pQueue)//只是查詢效果
{
    return (*pQueue).data[(*pQueue).back - 1];
}

void deQueue(Queue * pQueue)
{
    if (isEmpty(pQueue))
    {
        return;
    }
    --((*pQueue).back);
}

void showQueue(Queue * pQueue)
{
    for (int i = 0; i < (*pQueue).back; ++i)
    {
        printf("%4d", (*pQueue).data[i]);
    }
    printf("\n\n");
}
///01.佇列.c
#include "queue.h"
#include "Windows.h"
#include "process.h"

int main01(void)
{
    Queue myQueue;
    initQueue(&myQueue);
    for (int i = 99; i < 108; ++i)
    {
        enQueue(&myQueue, i);
        showQueue(&myQueue);
    }
    while (!isEmpty(&myQueue))
    {
        printf("%4d \n", getLast(&myQueue));
        deQueue(&myQueue);
        showQueue(&myQueue);
    }

    system("pause");
}

Queue myQueue;
void run(void * p)
{
    int * px = p;
    printf("執行緒編號是%d \n", *px);
    enQueue(&myQueue, *px);
}

//int intArr[10]-- > int * p = intArr;
int main02(void)
{
    initQueue(&myQueue);
    int intArr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    for (int i = 0; i < 10; ++i)
    {
        HANDLE hd = _beginthread(run, 0, &intArr[i]);
        WaitForSingleObject(hd, INFINITE);
        //WaitForMultipleObjects();
    }

    system("pause");//防止主執行緒提前結束
    showQueue(&myQueue);

    system("pause");
}

相關文章