20160224.CCPP體系詳解(0034天)

尹成發表於2016-03-20

程式片段(01):指標與結構體.c
內容概要:指標與結構體

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//01.養成編寫程式的良好習慣:
//  1.模組兒化程式設計,先進行每個模組兒測試可靠性:
//      模組兒化程式設計:將一個很大的專案分為多個模組兒進行分治處理,針對於每個模組兒進行分而治之
//      如同逐個針對於函式進行功能模組兒的處理,最後模組兒問題解決之後,再針對於整體的邏輯問題進行拼裝
//  2.每個獨立的函式解決獨立的問題:
//      在每一個獨立的函式當中進行獨立的功能封裝,強烈建議一個獨立的函式只封裝一個獨立的功能,不要糅合
//      在一起進行功能的封裝,為了實現高內聚低耦合的開發策略
//03.結構體的用處:
//  通過單個結構體來描述多個不同型別的資料,進行不同型別的資料彙總
//  注:自定義的一種資料結構體,用於儲存多元的資料
//04.區分標準結構體和非標準結構體:
//  非標準結構體:
//      char str[10];
//  標準結構體:
//      char * pStr;
//      int strLen;
//  注:C語言儘量採用動態記憶體操作!
typedef struct
{
    long long QQ;
    char * pPass;
    int passLen;
}Row;

//05.採用(結構體+動態記憶體)模擬一種儲存結構體的陣列,裡面的每個元素都是結構體
//  採用動態儲存空間模擬構建基於結構體的動態陣列模型
typedef struct
{
    Row * pRow;
    int rowNum;
}Array;

int main01(void)
{
    //建立一個基於堆記憶體的動態結構體陣列
    Array * pArr = (Array *)malloc(sizeof(Array));//pArray相當於動態陣列的首地址,也就是如同靜態陣列的陣列名稱(常量指標)-->變數指標
    (*pArr).rowNum = 10;//相當於所描述的堆記憶體結構體陣列當中的結構體個數
    //為結構體陣列執行初始化操作
    (*pArr).pRow = (Row *)malloc((*pArr).rowNum * sizeof(Row));
    //為動態陣列結構體當中的第一個結構體元素賦值
    //(*((*pArr).pRow + 0)).QQ = 77025077;
    pArr->pRow[0].QQ = 77025077;
    //(*((*pArr).pRow + 0)).pPass = (char *)malloc(10 * sizeof(char));
    pArr->pRow[0].pPass = (char *)malloc(10 * sizeof(char));
    //strcpy((*((*pArr).pRow + 0)).pPass , "yincheng");
    strcpy(pArr->pRow[0].pPass, "yincheng");
    //(*((*pArr).pRow + 0)).passLen = 10;
    pArr->pRow[0].passLen = 10;
    system("pause");
}

程式片段(02):連結串列.c
內容概要:連結串列簡單

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

//01.線性結構和鏈式結構的優缺點:
//  線性結構:(查詢+修改)效率比較高,(增加+刪除)效率比較低
//  鏈式結構:(查詢+修改)效率比較低,(增加+刪除)效率比較高
//02.線性結構和鏈式結構體的時間複雜度分析:
//  線性結構:
//      增加:N
//      刪除:N-1
//      修改:1
//      查詢:1
//  鏈式結構:
//      增加:1
//      刪除:1
//      修改:N
//      查詢:N
//  注:以上按照最壞情況進行統計
//03.鏈式結構程式設計特點:
//  按照圖形化方式進行連結串列節點的操作分析
//  增加+刪除+修改+查詢
//04.結構體在連結串列儲存結構當中的應用:
//  單個結構體模擬連結串列結構當中的某個節點
//  多個結構體模擬連結串列結構整體特點
//05.連結串列節點結構體的組成要素:
//  1.資料域:儲存資料
//  2.指標域:儲存下一個連結串列節點的首地址
//注:結構體當中不能包含和本結構體型別同型別
//  的結構體成員(因為這樣會形成死遞迴,無法確定
//  該結構體所應開闢的記憶體空間,然而替換成為指標
//  能行的原因是所有指標變數佔據相同尺寸的儲存空間)
typedef struct Node
{
    int data;//資料域
    struct Node * pNextLinkNode;//指標域
}LinkNode;

//06.在C語言的面試題目當中:
//  1.連結串列是必考點
//  2.通過遞迴方式遍歷連結串列節點
void showLinkList(LinkNode * pLinkList)
{
    if (NULL == pLinkList)
    {
        return;
    }                                  
    printf("%p, %d, %p \n", pLinkList, (*pLinkList).data, (*pLinkList).pNextLinkNode);
    showLinkList((*pLinkList).pNextLinkNode);
}

//07.連結串列結構的組成特點:
//  1.頭指標+首指標+尾指標+首節點+尾節點
//  2.組成要素分析:
//      頭指標:儲存整個連結串列結構的首地址
//      首指標:指向首節點的指標
//      尾指標:指向尾節點的指標
//      首節點:連結串列第一個節點
//      尾節點:連結串列最後一個節點(指標域為NULL)
int main01(void)
{
    //08.採用結構體模擬連結串列節點以及連結串列本身的儲存結構:
    LinkNode * pLinkList;//儲存連結串列首地址(首個連結串列節點的地址)-->頭指標
    LinkNode linkNode01;//獨立的連結串列資料儲存節點-->首節點
    linkNode01.data = 1;
    LinkNode linkNode02;
    linkNode02.data = 2;
    LinkNode linkNode03;
    linkNode03.data = 3;
    LinkNode linkNode04;
    linkNode04.data = 4;
    LinkNode linkNode05;//-->尾節點
    linkNode05.data = 5;
    pLinkList = &linkNode01;//指向連結串列的指標儲存連結串列首節點的地址
    linkNode01.pNextLinkNode = &linkNode02;
    linkNode02.pNextLinkNode = &linkNode03;//串聯每個獨立的連結串列資料節點
    linkNode03.pNextLinkNode = &linkNode04;
    linkNode04.pNextLinkNode = &linkNode05;
    linkNode05.pNextLinkNode = NULL;//結束該鏈式儲存結構

    //09.顯示鏈式儲存結構(連結串列)當中的每個獨立資料儲存節點所儲存的資料
    //printf("%d \n", pLinkList->data);
    //printf("%d \n", pLinkList->pNextLinkNode->data);
    //printf("%d \n", pLinkList->pNextLinkNode->pNextLinkNode->data);
    //printf("%d \n", pLinkList->pNextLinkNode->pNextLinkNode->pNextLinkNode->data);
    //printf("%d \n", pLinkList->pNextLinkNode->pNextLinkNode->pNextLinkNode->pNextLinkNode->data);

    //for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = pTmpNode->pNextLinkNode)
    //{//連結串列的迴圈遍歷
    //  printf("%p %d %p \n", pTmpNode, (*pTmpNode).data, (*pTmpNode).pNextLinkNode);
    //}

    showLinkList(pLinkList);

    system("pause");
}
//10.連結串列的三種遍歷方式:
//  1.逐個節點
//  2.迴圈遍歷
//  3.遞迴遍歷

程式片段(03):LinkList.h+LinkList.c+LinkListOnHeapTest.c
內容概要:LinkList

///LinkList.h
#pragma once

//01.資料結構概論:
//  1.儲存結構:
//      線性儲存:記憶體連續
//          靜態陣列+動態陣列
//      鏈式儲存:記憶體離散
//          靜態連結串列+動態連結串列
//  2.鏈式儲存:
//      單連結串列+雙連結串列+環形連結串列
//注:靜態(棧記憶體)+動態(堆記憶體)
//02.關於鏈式儲存結構的特點:
//  1.結構體和鏈式儲存密不可分
//  2.結構體和鏈式儲存的關聯:
//      單個結構體-->連結串列節點
//      多個機構提-->連結串列整體
//注:C語言的面試題必考內容就是連結串列
//      連結串列結構的最大優點就是可以充分
//      利用離散零碎的記憶體片段     
typedef struct Node
{//將鏈式儲存結構當中的每個鏈式節點都採用結構體進行模擬
    int data;//資料域
    struct Node * pNext;//指標域
}LinkNode;

void initLinkNode(LinkNode * pLinkNode);

//03.連結串列增加資料:
//  1.頭插+尾插+隨機
//  2.頭插涉及到連結串列整體首結點的改變,因此,需要重新修改連結串列的頭指標
//  3.跨函式修改記憶體的兩種方式:
//      返回值:會涉及到函式的返回值副本問題(返回更新地址)(效率低)
//      操地址:直接操作原本資料(傳遞變數地址)(效率較高)
void linkListHeadInsertData(LinkNode ** ppLinkList, int data);
void linkListTailInsertData(LinkNode ** ppLinkList, int data);

void showLinkList(LinkNode * pLinkList);
void revShowLinkList(LinkNode * pLinkList);

LinkNode * linkListSelectFirstData(LinkNode * pLinkList, int data);

void linkListRandInsertData(LinkNode ** pLinkList, int data, int insertData);

void linkListDeleteFirstData(LinkNode ** pLinkList, int data);
void linkListDeleteAllDatas(LinkNode ** pLinkList, int data);

void linkListUpdateFirstData(LinkNode * pLinkList, int oldData, int newData);
void linkListUpdateAllDatas(LinkNode * pLinkList, int oldData, int NewData);

int countLinkNodes(LinkNode * pLinkList);

void linkListRevByLoop(LinkNode ** ppLinkList);

LinkNode * linkListRevByRecu(LinkNode * ppLinkList);

void linkListBubbleSort(LinkNode * pLinkList);

void linkListQsort(LinkNode * pHeadNode, LinkNode * pTailNode);

void linkListQuick(LinkNode * pHeadNode, LinkNode * pTailNode);

//04.兩個有序連結串列的合併原理:連結串列合併演算法
//      例如:1  3  5  7  9-->連結串列一
//              2  4  6  8  10->連結串列二
//      合併:1  2  3  4  5  6  7  8  9  10-->連結串列三
//      原理:連結串列節點順序挨個對比
//          (1)迴圈遍歷連結串列一與連結串列二進行對比,進行指定位置的資料比較(肯定挨個位置進行比較)
//          (2)獲取較小的那個資料,將該資料插入到連結串列三當中[每次比較的都是連結串列頭部的資料]
//05. 查詢單連結串列的中間結點
//      例如:1 2 3 4 5        1 2 3  4 5 6
//              3                   3
//      原理:相對原理(差值原理)
//          (1)採用兩個指標並行前進,只不過前進的步伐不一樣
//          (2)當前進兩個步伐的指標已經到達終點,說明前進一個步伐的指標此時到達中點
//06.多個猴子圍成一圈兒,找到最終的一個猴子:猴子選大王
//      例如:多個猴子圍成一圈兒,每次數5個猴子,一旦數到第五個
//              就將其踢出去,留下最終一個猴子,就是大王
//      原理:環形連結串列原理(應用)
void linkListMerger(LinkNode * pLinkList1, LinkNode * pLinkList2, LinkNode ** ppLinkList);

LinkNode * linkListSelectMidNode(LinkNode * pLinkList);

int linkListIsCircleLinkList(LinkNode * pLinkList);

void showCircleLinkList(LinkNode * pLinkList);

LinkNode * circleLinkListGetEndNode(LinkNode ** ppCircleLinkList, int num);
///LinkList.c
#include "LinkList.h"
#include <stdlib.h>
#include <stdio.h>

void initLinkNode(LinkNode * pLinkNode)
{//初始化:恢復到初始狀態
    if (NULL == pLinkNode)
        abort();
    (*pLinkNode).data = 0;
    (*pLinkNode).pNext = NULL;
}

void linkListHeadInsertData(LinkNode ** ppLinkList, int data)
{
    LinkNode * pNewNode = (LinkNode *)malloc(sizeof(LinkNode));
    (*pNewNode).data = data;
    (*pNewNode).pNext = NULL;
    if (NULL == *ppLinkList)
    {
        *ppLinkList = pNewNode;
        return;
    }
    (*pNewNode).pNext = *ppLinkList;
    *ppLinkList = pNewNode;
}

void linkListTailInsertData(LinkNode ** ppLinkList, int data)
{
    LinkNode * pNewNode = (LinkNode *)malloc(sizeof(LinkNode));
    (*pNewNode).data = data;
    (*pNewNode).pNext = NULL;
    if (NULL == *ppLinkList)
    {
        *ppLinkList = pNewNode;
        return;
    }
    LinkNode * pTmpNode = *ppLinkList;//移交首節點指標
    while (NULL != (*pTmpNode).pNext)
    {
        pTmpNode = (*pTmpNode).pNext;
    }//獲取尾節點
    (*pTmpNode).pNext = pNewNode;
}

void showLinkList(LinkNode * pLinkList)
{
    if (NULL == pLinkList)
        return;
    //abort();
//for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = (*pTmpNode).pNext)
//{
//  printf("%p, %d, %p \n", pTmpNode, (*pTmpNode).data, (*pTmpNode).pNext);
//}
    printf("%p, %d, %p \n", pLinkList, (*pLinkList).data, (*pLinkList).pNext);
    showLinkList((*pLinkList).pNext);
}

void revShowLinkList(LinkNode * pLinkList)
{
    if (NULL == pLinkList)
        return;
    revShowLinkList((*pLinkList).pNext);
    printf("%p, %d, %p \n", pLinkList, (*pLinkList).data, (*pLinkList).pNext);
}

LinkNode * linkListSelectFirstData(LinkNode * pLinkList, int data)
{
    if (NULL == pLinkList)
        abort();
    for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = (*pTmpNode).pNext)
    {
        if (data == (*pTmpNode).data)
        {
            return pTmpNode;
        }
    }
    return NULL;
}

void linkListRandInsertData(LinkNode ** ppLinkList, int data, int insertData)
{
    if (NULL == *ppLinkList)
        abort();
    LinkNode *  pTmpNode1 = NULL, *pTmpNode2 = *ppLinkList;
    while (NULL != pTmpNode2)
    {
        if (data == (*pTmpNode2).data)
            break;
        pTmpNode1 = pTmpNode2;
        pTmpNode2 = (*pTmpNode2).pNext;
    }
    if (NULL == pTmpNode1 && data != (**ppLinkList).data)
    {
        return;
    }
    LinkNode * pNewNode = (LinkNode *)malloc(sizeof(LinkNode));
    (*pNewNode).data = insertData;
    (*pNewNode).pNext = NULL;
    if (NULL == pTmpNode1)
    {
        (*pNewNode).pNext = *ppLinkList;
        *ppLinkList = pNewNode;
    }
    else
    {
        (*pNewNode).pNext = pTmpNode2;
        (*pTmpNode1).pNext = pNewNode;
    }
}

//01.無論什麼樣兒的指標都必須進行初始化操作:
//  為了防止野指標存在(分清楚野指標和指標為空的區別)
//  野指標:沒有進行初始化的指標
//  指標為空:值為NULL的指標
void linkListDeleteFirstData(LinkNode ** ppLinkList, int data)
{
    if (NULL == *ppLinkList)
        return;
    LinkNode * pTmpNode1 = NULL, *pTmpNode2 = *ppLinkList;
    while (NULL != pTmpNode2)
    {
        if (data == (*pTmpNode2).data)
            break;
        pTmpNode1 = pTmpNode2;
        pTmpNode2 = (*pTmpNode2).pNext;
    }
    if (NULL == pTmpNode1 && data != (*(*ppLinkList)).data)
    {
        return;
    }
    if (NULL == pTmpNode1)
    {
        *ppLinkList = (*pTmpNode2).pNext;
    }
    else
    {
        (*pTmpNode1).pNext = (*pTmpNode2).pNext;
    }
    free(pTmpNode2);
}

void linkListUpdateFirstData(LinkNode * pLinkList, int oldData, int newData)
{
    if (NULL == pLinkList)
        abort();
    for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = (*pTmpNode).pNext)
    {
        if (oldData == (*pTmpNode).data)
        {
            (*pTmpNode).data = newData;
            break;
        }
    }
}

//02.關於陣列和連結串列的實戰特點:
//  1.由於陣列當中每個元素都有索引對應,而且該索引是有序的:
//      因此,陣列可以隨機訪問任何一個元素
//      因此,既可以採用從前往後的進行陣列元素訪問,也可以採用從後往前的陣列元素訪問
//      因此,既能使用正向冒泡也能採用反向冒泡
//  2.由於連結串列當中的每個元素都是採取上一個節點記錄下一個節點的指標的方式進行儲存
//      因此,連結串列只能採用從前往後的連結串列節點元素訪問的特點
//      因此,只能使用正向冒泡
void linkListBubbleSort(LinkNode * pLinkList)
{
    if (NULL == pLinkList)
        abort();
    for (LinkNode * pTmpNode1 = pLinkList; NULL != (*pTmpNode1).pNext; pTmpNode1 = (*pTmpNode1).pNext)
    {
        for (LinkNode * pTmpNode2 = (*pTmpNode1).pNext; NULL != pTmpNode2; pTmpNode2 = (*pTmpNode2).pNext)
        {
            if ((*pTmpNode1).data > (*pTmpNode2).data)
            {
                (*pTmpNode1).data = (*pTmpNode1).data ^ (*pTmpNode2).data;
                (*pTmpNode2).data = (*pTmpNode1).data ^ (*pTmpNode2).data;
                (*pTmpNode1).data = (*pTmpNode1).data ^ (*pTmpNode2).data;
            }
        }
    }
}

int countLinkNodes(LinkNode * pLinkList)
{
    //int linkNodeNum = 0;
    //for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = (*pTmpNode).pNext)
    //{
    //  ++linkNodeNum;
    //}
    //return linkNodeNum;
    if (NULL == pLinkList)
        return 0;
    return 1 + countLinkNodes((*pLinkList).pNext);
}

//03.單連結串列反轉所涉及到的幾個問題:
//  1.連結串列反轉的表現形式:
//      直接進行反向列印的效果(遞迴實現)
//  2.連結串列反轉的實現原理:
//      涉及到連續關聯的三個節點(指標),同時可以解決頭尾問題
//  3.連結串列反轉的實現要求:
//      不允許修改原始每個節點的資料(保持連結串列節點本身不變,節點資料域不變,無需開闢新空間)
//  4.連結串列反轉的實現要點:
//      迴圈方式:三根指標(模擬輪替)
//      遞迴方式:兩根指標+輪替
//  5.注意函式形參的副本機制影響
//      跨函式修改記憶體的兩種方式(返回值+傳地址)
void linkListRevByLoop(LinkNode ** ppLinkList)
{
    if (NULL == *ppLinkList || NULL == (*(*ppLinkList)).pNext)
    {//排除連結串列結構不存在的情況以及連結串列結構只包含單個資料節點的情況
        return;
    }
    LinkNode * pPreNode, *pCurNode, *pNextNode;//三個節點(指標)看做(整體移動)
    pPreNode = pCurNode = pNextNode = NULL;//指標變數(一定)要進行初始化操作
    pPreNode = *ppLinkList;
    pCurNode = (*(*ppLinkList)).pNext;
    while (NULL != pCurNode)
    {
        pNextNode = (*pCurNode).pNext;
        (*pCurNode).pNext = pPreNode;
        pPreNode = pCurNode;
        pCurNode = pNextNode;
    }
    (*(*ppLinkList)).pNext = NULL;
    *ppLinkList = pPreNode;
}

LinkNode * linkListRevByRecu(LinkNode * pLinkList)
{
    if (NULL == pLinkList || NULL == (*pLinkList).pNext)
    {
        return pLinkList;
    }
    LinkNode * pNextNode = (*pLinkList).pNext;
    LinkNode * pHeadNode = linkListRevByRecu(pNextNode);
    (*pNextNode).pNext = pLinkList;
    (*pLinkList).pNext = NULL;
    return pHeadNode;
}

LinkNode * getDivNode(LinkNode * pHeadNode, LinkNode * pTailNode)
{
    int divValue = (*pHeadNode).data;
    LinkNode * pTmpNode1 = pHeadNode;
    LinkNode * pTmpNode2 = (*pHeadNode).pNext;
    while (pTailNode != pTmpNode2)
    {
        if (divValue > (*pTmpNode2).data)
        {
            pTmpNode1 = (*pTmpNode1).pNext;
            int temp = (*pTmpNode1).data;
            (*pTmpNode1).data = (*pTmpNode2).data;
            (*pTmpNode2).data = temp;
        }
        pTmpNode2 = (*pTmpNode2).pNext;
    }
    int temp = (*pTmpNode1).data;
    (*pTmpNode1).data = (*pHeadNode).data;
    (*pHeadNode).data = temp;
    return pTmpNode1;
}

void linkListQsort(LinkNode * pHeadNode, LinkNode * pTailNode)
{
    if (pHeadNode == pTailNode)
        return;
    LinkNode * pDivNode = getDivNode(pHeadNode, pTailNode);
    linkListQsort(pHeadNode, pDivNode);
    linkListQsort((*pDivNode).pNext, pTailNode);
}

void linkListQuick(LinkNode * pHeadNode, LinkNode * pTailNode)
{
    if (pHeadNode == pTailNode)
        return;
    int divValue = (*pHeadNode).data;
    LinkNode * pTmpNode1 = pHeadNode;
    for (LinkNode * pTmpNode2 = (*pHeadNode).pNext; NULL != pTmpNode2; pTmpNode2 = (*pTmpNode2).pNext)
    {
        if (divValue > (*pTmpNode2).data)
        {
            pTmpNode1 = (*pTmpNode1).pNext;
            int temp = (*pTmpNode1).data;
            (*pTmpNode1).data = (*pTmpNode2).data;
            (*pTmpNode2).data = temp;
        }
    }
    int temp = (*pTmpNode1).data;
    (*pTmpNode1).data = (*pHeadNode).data;
    (*pHeadNode).data = temp;
    linkListQuick(pHeadNode, pTmpNode1);
    linkListQuick((*pTmpNode1).pNext, pTailNode);
}

void linkListMerger(LinkNode * pLinkList1, LinkNode * pLinkList2, LinkNode ** ppLinkList3)
{
    if (NULL == pLinkList1 || NULL == pLinkList2)
        abort();
    while (NULL != pLinkList1 || NULL != pLinkList2)
    {
        if (NULL != pLinkList1 && NULL != pLinkList2)
        {
            if ((*pLinkList1).data < (*pLinkList2).data)
            {
                linkListTailInsertData(ppLinkList3, (*pLinkList1).data);
                pLinkList1 = (*pLinkList1).pNext;
            }
            else
            {
                linkListTailInsertData(ppLinkList3, (*pLinkList2).data);
                pLinkList2 = (*pLinkList2).pNext;
            }
        }
        else
        {
            while (NULL != pLinkList1)
            {
                linkListTailInsertData(ppLinkList3, (*pLinkList1).data);
                pLinkList1 = (*pLinkList1).pNext;
            }
            while (NULL != pLinkList2)
            {
                linkListTailInsertData(ppLinkList3, (*pLinkList2).data);
                pLinkList2 = (*pLinkList2).pNext;
            }
        }
    }
}

LinkNode * linkListSelectMidNode(LinkNode * pLinkList)
{
    if (NULL == pLinkList || NULL == (*pLinkList).pNext)
        return pLinkList;
    LinkNode * pTmpNode1 = pLinkList;
    LinkNode * pTmpNode2 = (*pLinkList).pNext;
    while (NULL != pTmpNode2)
    {
        if (NULL == (pTmpNode2 = pTmpNode2->pNext))
            break;
        pTmpNode2 = pTmpNode2->pNext;
        pTmpNode1 = pTmpNode1->pNext;
    }
    return pTmpNode1;
}

int linkListIsCircleLinkList(LinkNode * pLinkList)
{
    if (NULL == pLinkList)
        return 0;
    LinkNode * pTmpNode1 = pLinkList;
    LinkNode * pTmpNode2 = (*pLinkList).pNext;
    while (NULL != pTmpNode2)
    {
        if ((*pTmpNode1).data == (*pTmpNode2).data)
            return 1;
        if (NULL == (pTmpNode2 = (*pTmpNode2).pNext))
            return 0;
        if (NULL == (pTmpNode2 = (*pTmpNode2).pNext))
            return 0;
        pTmpNode1 = (*pTmpNode1).pNext;
    }
    return 0;
}

void showCircleLinkList(LinkNode * pCircleLinkList)
{
    if (NULL == pCircleLinkList)
        abort();
    LinkNode * pTmpNode = pCircleLinkList;
    do
    {
        printf("%4d", (*pTmpNode).data);
        pTmpNode = (*pTmpNode).pNext;
    } while (pCircleLinkList != pTmpNode);
}

LinkNode * circleLinkListGetEndNode(LinkNode ** ppCircleLinkList, int num)
{

}
///LinkListOnHeapTest.c
#include "LinkList.h"
#include <stdlib.h>
#include <stdio.h>

//01.單連結串列:
//  1.頭指標:
//      頭指標不會儲存獨立結構體的指標
//      而是會儲存整個連結串列結構的指標
//      (換而言之,就是會儲存整個連結串列結構的首節點的指標)
//  2.初始化:
//      恢復到初始的狀態(此狀態可能有資料,也可能沒有資料!)
int main01(void)
{
    LinkNode * pLinkList = NULL;//頭指標:指向整個連結串列結構的指標
    //initLinkNode(pLinkList);//初始化一個節點,但是不可以初始化頭結點
    linkListTailInsertData(&pLinkList, 1);
    linkListTailInsertData(&pLinkList, 2);
    linkListTailInsertData(&pLinkList, 3);
    linkListTailInsertData(&pLinkList, 6);
    linkListTailInsertData(&pLinkList, 5);
    linkListTailInsertData(&pLinkList, 4);
    //showLinkList(pLinkList);
    //linkListHeadInsertData(&pLinkList, 4);
    //showLinkList(pLinkList);
    //revShowLinkList(pLinkList);
    //printf("%d \n", (*linkListSelectFirstData(pLinkList, 2)).data);
    //linkListRandInsertData(&pLinkList, 3, 4);
    //linkListDeleteFirstData(&pLinkList, 2);
    //linkListUpdateFirstData(pLinkList, 2, 4);
    //linkListBubbleSort(pLinkList);
    //printf("linkListNodeNum:%d \n", countLinkNodes(pLinkList));
    //linkListRevByLoop(&pLinkList);
    //pLinkList = linkListRevByRecu(pLinkList);
    //linkListQsort(pLinkList, NULL);
    linkListQuick(pLinkList, NULL);
    showLinkList(pLinkList);

    system("pause");
}

int main02(void)
{
    LinkNode * pLinkList1 = NULL;//頭指標:代表連結串列整體是否存在;頭結點:根本不會直接儲存資料
    linkListTailInsertData(&pLinkList1, 2);
    linkListTailInsertData(&pLinkList1, 4);
    linkListTailInsertData(&pLinkList1, 6);
    linkListTailInsertData(&pLinkList1, 8);
    linkListTailInsertData(&pLinkList1, 10);
    linkListTailInsertData(&pLinkList1, 12);
    linkListTailInsertData(&pLinkList1, 14);
    LinkNode * pLinkList2 = NULL;
    linkListTailInsertData(&pLinkList2, 1);
    linkListTailInsertData(&pLinkList2, 3);
    linkListTailInsertData(&pLinkList2, 5);
    linkListTailInsertData(&pLinkList2, 7);
    linkListTailInsertData(&pLinkList2, 9);
    linkListTailInsertData(&pLinkList2, 11);
    linkListTailInsertData(&pLinkList2, 13);
    LinkNode * pLinkList3 = NULL;
    linkListMerger(pLinkList1, pLinkList2, &pLinkList3);
    showLinkList(pLinkList3);
    printf("midValue = %d \n", (*linkListSelectMidNode(pLinkList3)).data);


    system("pause");
}

int main(void)
{
    LinkNode * pCircleLinkList = NULL;
    linkListTailInsertData(&pCircleLinkList, 1);
    linkListTailInsertData(&pCircleLinkList, 2);
    linkListTailInsertData(&pCircleLinkList, 3);
    linkListTailInsertData(&pCircleLinkList, 4);
    linkListTailInsertData(&pCircleLinkList, 5);
    linkListTailInsertData(&pCircleLinkList, 6);
    linkListTailInsertData(&pCircleLinkList, 7);
    linkListTailInsertData(&pCircleLinkList, 8);
    linkListTailInsertData(&pCircleLinkList, 9);
    LinkNode * pTailNode = linkListSelectFirstData(pCircleLinkList, 9);
    (*pTailNode).pNext = pCircleLinkList;
    //printf("linkListIsCircleLinkList:%d \n", linkListIsCircleLinkList(pCircleLinkList));
    showCircleLinkList(pCircleLinkList);

    system("pause");
}

程式片段(04):陣列快速排序.c
內容概要:快速排序法

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

void showArray(int * pArr, int len)
{
    for (int i = 0; i < len; ++i)
    {
        printf("%4d", *(pArr + i));
    }
    printf("\n");
}

void arrayQsort(int * pArr, int startI, int endI)
{
    if (startI < endI)
    {
        int i = startI;
        for (int j = i + 1; j <= endI; ++j)
        {
            if (*(pArr + j) < *(pArr + startI))
            {
                ++i;
                int temp = pArr[i];
                pArr[i] = pArr[j];
                pArr[j] = temp;
            }
        }
        int temp = pArr[startI];
        pArr[startI] = pArr[i];
        pArr[i] = temp;
        arrayQsort(pArr, startI, i - 1);
        arrayQsort(pArr, i + 1, endI);
    }
}

int main(void)
{
    int arr[10] = { 10, 11, 9, 17, 8, 29, 5, 39, 6, 102 };
    showArray(arr, 10);
    arrayQsort(arr, 0, 9);
    showArray(arr, 10);
    system("pause");
}

相關文章