• 20160224.CCPP体系详解(0034天)


    程序片段(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 
    ", 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 
    ", pLinkList->data);
        //printf("%d 
    ", pLinkList->pNextLinkNode->data);
        //printf("%d 
    ", pLinkList->pNextLinkNode->pNextLinkNode->data);
        //printf("%d 
    ", pLinkList->pNextLinkNode->pNextLinkNode->pNextLinkNode->data);
        //printf("%d 
    ", pLinkList->pNextLinkNode->pNextLinkNode->pNextLinkNode->pNextLinkNode->data);
    
        //for (LinkNode * pTmpNode = pLinkList; NULL != pTmpNode; pTmpNode = pTmpNode->pNextLinkNode)
        //{//链表的循环遍历
        //  printf("%p %d %p 
    ", 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 
    ", pTmpNode, (*pTmpNode).data, (*pTmpNode).pNext);
    //}
        printf("%p, %d, %p 
    ", pLinkList, (*pLinkList).data, (*pLinkList).pNext);
        showLinkList((*pLinkList).pNext);
    }
    
    void revShowLinkList(LinkNode * pLinkList)
    {
        if (NULL == pLinkList)
            return;
        revShowLinkList((*pLinkList).pNext);
        printf("%p, %d, %p 
    ", 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 
    ", (*linkListSelectFirstData(pLinkList, 2)).data);
        //linkListRandInsertData(&pLinkList, 3, 4);
        //linkListDeleteFirstData(&pLinkList, 2);
        //linkListUpdateFirstData(pLinkList, 2, 4);
        //linkListBubbleSort(pLinkList);
        //printf("linkListNodeNum:%d 
    ", 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 
    ", (*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 
    ", 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("
    ");
    }
    
    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");
    }
  • 相关阅读:
    Subversion版本控制系统的安装和操作.
    java基础
    iOS_第3方类库MBprogressHUD
    wikioi 1396 伸展树(两个模板)
    从乐视和小米“最火电视”之战 看PR传播策略
    Android开发之大位图压缩水印处理
    Spark SQL with Hive
    PHP设计模式——模板模式
    Nginx 配置 gzip 压缩
    SecureCRT学习之道:SecureCRT 经常使用技巧
  • 原文地址:https://www.cnblogs.com/new0801/p/6176803.html
Copyright © 2020-2023  润新知