Loading

链表

用C语言来实现一个单向链表的增、查、改、删。以及约瑟夫环,链表倒置,插入排序等

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

typedef int DataType;//一是表明该类型的特殊作用,二是将来有可能要改变这种类型(比如提高精度),可以统一修改

typedef struct Node
{
    DataType Data;
    struct Node *pNext;
}LinkNode;

typedef struct List
{
    LinkNode *pHead;
    int      cLen;
}LinkList;

//判空函数
bool isEmptyLinkList(LinkList *pList)
{
    return pList->pHead == NULL;
}

//创建一个链表
LinkList *createLinkList()
{
    LinkList *pList = malloc(sizeof(LinkList));
    //为了解决C语言中NULL代指空指针存在的二义性问题,在C++11版本(2011年发布)中特意引入了
    //nullptr这一新的关键字来代指空指针
    if(NULL == pList)
    {
        perror("fail to create!");
    }
    pList->pHead = NULL;
    pList->cLen = 0;
    return pList;
}

//头插
int insertHeadLinkList(LinkList *pList, DataType value)
{
    LinkNode *pNew = malloc(sizeof(LinkNode));
    if(NULL == pNew)
    {
        perror("fail to create!");
        return -1;
    }
    pNew->Data = value;
    pNew->pNext = pList->pHead;
    pList->pHead = pNew;
    ++pList->cLen;
    return 0;
}

//尾插
int insertTailLinkList(LinkList *pList, DataType value)
{
    if(isEmptyLinkList(pList))
    {
        insertHeadLinkList(pList,value);
    }
    else
    {
        LinkNode *pNew = malloc(sizeof(LinkNode));
        if(NULL == pNew)
        {
            perror("fail to create!");
            return -1;
        }
        pNew->Data = value;
        pNew->pNext = NULL;
        LinkNode *pTemp = pList->pHead;
        while(pTemp->pNext != NULL)
        {
            pTemp = pTemp->pNext;
        }
        pTemp->pNext = pNew;
        ++pList->cLen;

    }
    return 0;
}

//头删
int deleteHeadLinkList(LinkList *pList)
{
    if(!isEmptyLinkList(pList))
    {
        LinkNode *pTemp = pList->pHead;
        pList->pHead = pTemp->pNext;
        free(pTemp);
        --pList->cLen;
    }
    return 0;
}

//尾删
int deleteTailLinkList(LinkList *pList)
{
    if(!isEmptyLinkList(pList))
    {
        if(1 == pList->cLen)
        {
            deleteHeadLinkList(pList);
        }
        else if(2 <= pList->cLen)
        {
            LinkNode *pTemp = pList->pHead;
            while(pTemp->pNext->pNext != NULL)
            {
                pTemp = pTemp->pNext;
            }
            free(pTemp->pNext);
            pTemp->pNext = NULL;
            --pList->cLen;
        }
    }
    return 0;
}

//查找
LinkNode *findLinkNode(LinkList *pList, DataType value)
{
    if(!isEmptyLinkList(pList))
    {
        LinkNode *pTemp = pList->pHead;
        while(pTemp != NULL)
        {
            if(pTemp->Data == value)
            {
                return pTemp;
            }
            pTemp = pTemp->pNext;
        }
        if(pTemp == NULL)
        {
            printf("no find!\n");
        }
        return NULL;
    }
    else
    {
        printf("List is empty!\n");
    }
    return NULL;
}

//修改链表数据
int modifyLinkList(LinkList *pList, int oldValue, DataType newValue)
{
    LinkNode *pTemp = findLinkNode(pList, oldValue);
    if(pTemp != NULL)
    {
        pTemp->Data = newValue;
        return 1;
    }
    return 0;
}

//打印链表中结点个数及各结点数据
void showLinkList(LinkList *pList)
{
    if(isEmptyLinkList(pList))
    {
        printf("Linklist is empty!\n");
    }
    else
    {
        printf("Linklist's cLen:%d\n",pList->cLen);
        LinkNode *pTemp = pList->pHead;
        printf("Linklist's data:");
        while(pTemp != NULL)
        {
            printf("%d ",pTemp->Data);
            pTemp = pTemp->pNext;
        }
        printf("\n");
    }
}

//摧毁链表
void destroyLinkList(LinkList **ppList)
{
    if(isEmptyLinkList(*ppList))
    {
        free(*ppList);
    }
    else
    {
        while((*ppList)->pHead != NULL)
        {
            deleteHeadLinkList(*ppList);
        }
        free(*ppList);
        *ppList = NULL;
    }
}


//快慢指针法求链表的中间结点
LinkNode *findMidLinkList(LinkList *pList)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pList->pHead;
    while(pFast != NULL)
    {     
        pFast = pFast->pNext;
        if(pFast == NULL)
        {
            break;
        }
        else
        {
            pFast = pFast->pNext;
            pSlow = pSlow->pNext;
        }
    }
    return pSlow;
}

//寻找链表倒数第K个数据
LinkNode *FindLastKNode(LinkList *pList, DataType k)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pList->pHead;
    for(int i = 0;i < k;++i)
    {
        pFast = pFast->pNext;
    }
    while(pFast != NULL)
    {
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
    }
    return pSlow;
}

//判断链表是否为环形
int isLoopLinkList(LinkList *pList)
{
    LinkNode *pFast = pList->pHead;
    LinkNode *pSlow = pFast;
    while(pFast != NULL)
    {
        pFast = pFast->pNext;
        if(pFast == NULL)
        {
            return 0;
        }
        pFast = pFast->pNext;
        pSlow = pSlow->pNext;
        if(pFast == pSlow)
        {
            return 1;
        }
    }
    return 0;
}

//约瑟夫环
LinkNode *joseF(LinkList *pList)
{
    LinkNode *pTmpNode = pList->pHead;
    LinkNode *pPreNode = NULL;
    while(pList->cLen > 1)
    {
        pPreNode = pTmpNode;
        pTmpNode = pTmpNode->pNext->pNext;
        pPreNode = pPreNode->pNext;
        pPreNode->pNext = pTmpNode->pNext;
        free(pTmpNode);
        pTmpNode = pPreNode->pNext;
        --pList->cLen;
    }
    return pTmpNode;
}

//链表倒置
void reverseLinkList(LinkList *pList)
{
    LinkNode *pTmpNode = pList->pHead;
    LinkNode *pInsertNode = NULL;
    pList->pHead = NULL;
    while(pTmpNode != NULL)
    {
        pInsertNode = pTmpNode;
        pTmpNode = pTmpNode->pNext;
        pInsertNode->pNext = pList->pHead;
        pList->pHead = pInsertNode;
    }
}

//删除链表指定位置的结点
int deleteKLinkList(LinkList *pList, DataType value)
{
    if(isEmptyLinkList(pList))
    {
        return 0;
    }
    LinkNode *pTmpNode = pList->pHead;
    LinkNode *pPreNode = pList->pHead;
    while(pTmpNode != NULL)
    {
        if(pTmpNode->Data == value)
        {
            if(pTmpNode == pPreNode)
            {
                pList->pHead = pPreNode->pNext;
                free(pTmpNode);
                pTmpNode = pList->pHead;
                pPreNode = pList->pHead;
            }
            else
            {
                pPreNode->pNext = pTmpNode->pNext;
                free(pTmpNode);
                pTmpNode = pPreNode->pNext;
            }
            --pList->cLen;
        }
        else
        {
            pPreNode = pTmpNode;
            pTmpNode = pTmpNode->pNext;
        }
    }
    return 1;
}

//插入排序
int insertSortLinkList(LinkList *pList)
{
    if(isEmptyLinkList(pList) || pList->cLen == 1)
    {
        return 0;
    }
    //将链表从第一个结点断开
    LinkNode *pTmpNode = pList->pHead->pNext;
    LinkNode *pInsertNode = NULL;
    pList->pHead->pNext = NULL;
    while(pTmpNode != NULL)
    {
        pInsertNode = pTmpNode;
        pTmpNode = pTmpNode->pNext;
        pInsertNode->pNext = NULL;
        if(pInsertNode->Data < pList->pHead->Data)
        {
            pInsertNode->pNext = pList->pHead;
            pList->pHead = pInsertNode;
        }
        else
        {
            LinkNode *pTemp = pList->pHead;
            while(pTemp!=NULL && pTemp->pNext!=NULL && pTemp->pNext->Data < pInsertNode->Data)
            {
                pTemp = pTemp->pNext;
            }
            pInsertNode->pNext = pTemp->pNext;
            pTemp->pNext = pInsertNode;
        }
    }
    return 0;
}

//主函数
int main(void)
{
    LinkList *pList = NULL;
    pList = createLinkList();      //创建链表
    insertHeadLinkList(pList, 10); //插入数据
    insertTailLinkList(pList, 30);
    insertTailLinkList(pList, 20);
    insertTailLinkList(pList, 40);
    insertTailLinkList(pList, 60);
    insertTailLinkList(pList, 50);
    insertTailLinkList(pList, 70);
    insertTailLinkList(pList, 80);
    showLinkList(pList);
    deleteKLinkList(pList,20);
    showLinkList(pList);
    insertSortLinkList(pList);
    showLinkList(pList);
//    reverseLinkList(pList);        //链表倒置
//    showLinkList(pList);
//    deleteTailLinkList(pList);     //删除尾部数据
//    showLinkList(pList);
//    deleteHeadLinkList(pList);     //删除头部数据
//    showLinkList(pList);
//    modifyLinkList(pList, 20, 50); //将链表中的第一个20修改为50
//    showLinkList(pList);
//    LinkNode *pTmp = NULL;
//    pTmp = findLinkNode(pList, 30);//寻找链表中的30
//    destroyLinkList(&pList);       //摧毁链表
//    LinkNode *pFindMid = NULL;
//    pFindMid = findMidLinkList(pList);
//    printf("%d\n",pFindMid->Data);
//    LinkNode *pFindKLast = NULL;
//    pFindKLast = FindLastKNode(pList, 3);
//    printf("%d\n",pFindKLast->Data);
    return 0;
}

再来一个双向链表

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

//双向链表
typedef struct Student
{
    int id;
    int score;
    char name[32];
}DataTpye;

typedef struct Node
{
    DataTpye data;
    struct Node *pPre;//不能在typedef类型之前使用它,如 DouNode *pPre;
    struct Node *pNext;
}DouNode;

typedef struct List
{
    int cLen;
    DouNode *pHead;
}DouList;

//创建双向链表
DouList *createDouList()
{
    DouList *pList = malloc(sizeof(DouList));
    if(pList == NULL)
    {
        perror("fail to create!");
    }
    pList->cLen = 0;
    pList->pHead = NULL;
    return pList;
}

//判空函数
bool isEmptyDouList(DouList *pList)
{
    return (pList->pHead == NULL);
}

//显示双向链表数据
void showDouList(DouList *pList, int dir)
{
    if(isEmptyDouList(pList))
    {
        return ;
    }
    DouNode *pTemp = pList->pHead;
    if(dir == 1)
    {
        printf("cLen's number:%d\n",pList->cLen);
        while(pTemp != NULL)
        {
            printf("%s %d %d\n", pTemp->data.name, pTemp->data.id, pTemp->data.score);
            pTemp = pTemp->pNext;
        }
    }
    else if(dir == 0)
    {
        printf("cLen's number:%d\n",pList->cLen);
        while(pTemp->pNext != NULL)
        {
            pTemp = pTemp->pNext;
        }
        while(pTemp != NULL)
        {
            printf("%s %d %d\n", pTemp->data.name, pTemp->data.id, pTemp->data.score);
            pTemp = pTemp->pPre;
        }
    }
    printf("\n");
}

//头插
int insertHeadDouNode(DouList *pList, DataTpye *pdata)
{
    DouNode *pNew = malloc(sizeof(DouNode));  //必须得在堆区开辟空间
    memcpy(&pNew->data, pdata, sizeof(DataTpye));

    pNew->pPre = NULL;
    pNew->pNext = pList->pHead;

    if(pList->pHead != NULL)
    {
        pList->pHead->pPre = pNew;
    }
    pList->pHead = pNew;
    ++pList->cLen;
    return 1;
}

//尾插
int insertTailDouNode(DouList *pList, DataTpye *pdata)
{
    if(pList->pHead == NULL)
    {
        insertHeadDouNode(pList, pdata);
    }
    if(pList->cLen >= 1)
    {
        DouNode *pNew = malloc(sizeof(DouNode));
        memcpy(&pNew->data, pdata, sizeof(DataTpye));
        pNew->pNext = NULL;
        DouNode *pTemp = pList->pHead;
        while(pTemp->pNext != NULL)
        {
            pTemp = pTemp->pNext;
        }
        pTemp->pNext = pNew;
        pNew->pPre = pTemp;
        ++pList->cLen;
    }
    return 1;
}

//头删
int deleteHeadNodList(DouList *pList)
{
    if(!isEmptyDouList(pList))
    {
        DouNode *pTemp = pList->pHead;
        pList->pHead = pTemp->pNext;
        if(pTemp->pNext != NULL)
        {
            pTemp->pNext->pPre = NULL;
        }
        free(pTemp);
        --pList->cLen;
    }
    return 1;
}

//尾删
int deleteTailNodList(DouList *pList)
{
    if(isEmptyDouList(pList))
    {
        return 0;
    }
    if(pList->cLen == 1)
    {
        deleteHeadNodList(pList);
    }
    if(pList->cLen > 1)
    {
        DouNode *pTemp = pList->pHead;
        while(pTemp->pNext != NULL)
        {
            pTemp = pTemp->pNext;
        }
        pTemp->pPre->pNext = NULL;
        free(pTemp);
        --pList->cLen;
    }
    return 1;
}

//摧毁链表
void destroyDouList(DouList **ppList)
{
    if((*ppList)->pHead != NULL)
    {
        deleteHeadNodList(*ppList);
    }
    free(*ppList);
    *ppList = NULL;
}

int main(void)
{
    DouList *pList = NULL;
    pList = createDouList();//创建链表
    DataTpye stu[3] = {{1, 99, "zhangsan"}, {2, 91, "lisi"}, {3, 92, "wangwu"}};
    insertHeadDouNode(pList, &stu[0]);
    insertHeadDouNode(pList, &stu[1]);
    insertTailDouNode(pList, &stu[2]);
    showDouList(pList, 1);
    deleteTailNodList(pList);
    deleteHeadNodList(pList);
    showDouList(pList, 1);
}

posted @ 2020-10-12 16:48  小森林呐  阅读(116)  评论(0编辑  收藏  举报