【数据结构】双向循环链表实现

先来看一下双向链表和双向循环链表的逻辑结构:

下面我们将用c/c++语言实现双向循环链表:

#include <iostream>
#include <malloc.h>
#include <windows.h>

using namespace std;

typedef struct _DATA_//数据
{
    char name[40];
}Data,*pData;

typedef struct _NODE_//节点
{
    Data data;//数据域
    //指针域
    _NODE_* pNext;//后继指针
    _NODE_* pPre;//前驱指针
}Node,*pNode;

typedef struct _TABLE_//管理员
{
    pNode pHead;//头指针(头节点)
    pNode pTail;//尾指针(尾节点)

    int nodeCount;//节点数
}Table,*pTable;


//
//声明
pNode createNode(Data data);//创建节点
void linkNode(pTable pTableTemp,pNode pNodeNew);//将创建的节点插入链表
void printList(pTable pTableTemp);//遍历链表
int getNodeCount(pTable pTableTemp);//返回节点个数
void freeList(pTable pTableTemp);//释放所有节点

pNode findNode(pTable pTableTemp,char* name);//查找节点
void deleteNode(pTable pTableTemp,pNode pNodeTemp);//删除节点
/
//测试
int main(void)
{
    Table table = {0};
    Data data = {0};
    char temp[40]; 
    for(int i = 0; i < 4; i++)
    {
        cout<<"input name:";
        cin>>data.name;
        pNode pNodeTemp = createNode(data);
        linkNode(&table,pNodeTemp);
    }
    printList(&table);

    cout<<"input data to del:";
    cin>>temp;
    pNode pNodeDel = findNode(&table,temp);
    if(pNodeDel != NULL)
    {
        deleteNode(&table,pNodeDel);
    }
    printList(&table);
    freeList(&table);
    return 0;
}

//具体实现
pNode createNode(Data data)
{
    pNode pNodeNew = (pNode)malloc(sizeof(Node));//申请内存
    if(pNodeNew != NULL)//申请成功
    {
        pNodeNew->data = data;//数据域赋值
        pNodeNew->pNext = pNodeNew->pPre = NULL;//指针域赋值
        return pNodeNew;//返回新生成的节点
    }
    return NULL;//失败时返回空
}
void linkNode(pTable pTableTemp,pNode pNodeNew)//节点插入
{
    if(pTableTemp->pHead == NULL)//如果头指针为空
    {
        pTableTemp->pHead = pTableTemp->pTail = pNodeNew;//头指针和尾指针均指向新节点
        pTableTemp->pHead->pPre = pTableTemp->pTail->pNext = pNodeNew;//对节点的指针域赋值(指向自身)
    }
    else//否则
    {
        pTableTemp->pTail->pNext = pNodeNew;//尾节点的后继指针指向新节点
        pTableTemp->pHead->pPre = pNodeNew;//头节点的前驱指针指向新节点
        pNodeNew->pPre = pTableTemp->pTail;//新节点的前驱指针指向尾节点
        pNodeNew->pNext = pTableTemp->pHead;//新节点的后继指针指向首节点

        pTableTemp->pTail = pNodeNew;//尾指针后移,并指向新生成的节点
    }
    pTableTemp->nodeCount++;//节点数++
}
void printList(pTable pTableTemp)
{
    pNode pNodeTemp = pTableTemp->pHead;
    for(int i = 0; i < pTableTemp->nodeCount; i++)
    {
        cout<<pNodeTemp->data.name<<" ";
        pNodeTemp = pNodeTemp->pNext;
    }
    cout<<endl;
}
int getNodeCount(pTable pTableTemp)
{
    return pTableTemp->nodeCount;
}
void freeList(pTable pTableTemp)
{
    if(pTableTemp != NULL)
    {
        pNode pNodeTemp = pTableTemp->pHead;
        pNode pNodeDel = NULL;
        for(int i = 0; i < pTableTemp->nodeCount; i++)
        {
            pNodeDel = pNodeTemp->pNext;
            free(pNodeTemp);
            pNodeTemp = pNodeDel;
        }
    }
}
pNode findNode(pTable pTableTemp,char* name)
{
    pNode pNodeTemp = pTableTemp->pHead;
    int iOK = -1;
    for(int i = 0; i < pTableTemp->nodeCount; i++)
    {
        iOK = strcmp(name,pNodeTemp->data.name);
        if(iOK == 0)
        {
            return pNodeTemp;            
        }
        else
        {
            pNodeTemp = pNodeTemp->pNext;
        }
    }
    return NULL;
}
void deleteNode(pTable pTableTemp,pNode pNodeTemp)
{
    if(pNodeTemp == pTableTemp->pHead)//待删除节点为头节点
    {
        pTableTemp->pHead = pNodeTemp->pNext;
        pTableTemp->pTail->pNext = pTableTemp->pHead;
    }
    else if(pNodeTemp == pTableTemp->pTail)//待删除节点为尾节点
    {
        pTableTemp->pTail = pNodeTemp->pPre;
        pTableTemp->pHead->pPre = pTableTemp->pTail;
    }
    else//待删除节点为中间节点
    {
        pNodeTemp->pNext->pPre = pNodeTemp->pPre;
        pNodeTemp->pPre->pNext = pNodeTemp->pNext;
    }
    free(pNodeTemp);//释放节点
    pTableTemp->nodeCount--;
}


 

需要注意的是,插入删除算法。
插入分两种情况,如果链表为空,逻辑结构如下图:

如果链表不为空,则逻辑结构如下:

应该针对不同情况分别处理.

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值