数据结构【单向循环链表】

单向循环链表:

数据结构示意图1.1.1如下:
在这里插入图片描述
图1.1.1 链表节点结构示意图

让代码来讲话吧:

Structure.h
//
// Created by Today me on 2021/7/11.
//

#ifndef DATA_STRUCTURE_SCNLIST_STRUCTURE_H
#define DATA_STRUCTURE_SCNLIST_STRUCTURE_H
#include <iostream>

using namespace std;
/*-------------------1.链表----------------------*/
#define HeadM pHead->mark = 0   //设置链表头结点pHead的mark为0
// (1)单向链表:
// (2)单向循环链表:
typedef struct SCNode {
    int date;           //数据
    unsigned int mark;  //第mark个节点
    SCNode *pNext;       //节点尾指针
} SN,                   //单向
SCN;                    //单向循环
//二者数据结构相同
//=============================================//
// (3)双向链表:
// (4)双向循环链表:
typedef struct DNode {
    int date;           //数据
    unsigned int mark;  //第mark个节点
    DNode *pPrev;       //节点头指针
    DNode *pNext;       //节点尾指针
} DN,                   //双向
DCN;                    //双向循环
//二者数据结构相同
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_SCNLIST_STRUCTURE_H

Structure.cpp
//
// Created by Today me on 2021/7/11.
//

#include "Structure.h"
#include "Operation.h"

/*-------------------1.链表----------------------*/
// (2)单向循环链表:
//遍历整个链表,返回相对头结点的尾节点
SCN *FindTail(SCN *pHead) {
    SCN *pNTemp = pHead,*pNTemp01 = pHead;
    while ((pHead = pHead->pNext) != pNTemp)pNTemp01 = pNTemp01->pNext;
    return pNTemp01;
}

//查找任意节点[调用此函数前,需确保List中mark的顺序性]
SCN *FindNode(SCN *pHead, int pos) {
    while (pos != pHead->mark) {
        pHead = pHead->pNext;
    }
    return pHead;
}

//规律化NODE[mark]
SCN *RegularMark(SCN *pHead) {
    SCN *pNTemp = pHead;
    int count = 0;
    do {
        pHead->mark = count++;
        pHead = pHead->pNext;
    }while (pNTemp != pHead);
    return pNTemp;
}
/*-------------------1.链表----------------------*/
Operation.h
//
// Created by Today me on 2021/7/11.
//

#ifndef DATA_STRUCTURE_SCNLIST_OPERATION_H
#define DATA_STRUCTURE_SCNLIST_OPERATION_H

#include "Structure.h"
/*-------------------1.链表----------------------*/

// (1)单向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:
// (2)单向循环链表:
SCN *FindTail(SCN *pHead);                //遍历整个链表,返回相对头结点的尾节点
SCN *FindNode(SCN *pHead, int pos);       //查找任意节点[调用此函数前,需确保List中mark的顺序性]
SCN *RegularMark(SCN *pHead);             //规律化NODE[mark]
//  a.创建链表:
SCN *CreateHead();

//  b.插入节点:1.头插     2.尾插    3.中间插
SCN *InsertHead(SCN *pHead);              //1.头插
SCN *InsertTail(SCN *pHead);              //2.尾插
SCN *InsertMiddle(SCN *pHead, int pos);    //3.中间插

//  c.删除节点:1.头删     2.尾删    3.中间删
SCN *DeleteHead(SCN *pHead);              //1.头插
SCN *DeleteTail(SCN *pHead);              //2.尾插
SCN *DeleteMiddle(SCN *pHead, int pos);    //3.中间插

//  d.打印链表:
unsigned int DisplayList(SCN *pHead);
// (3)双向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:
// (4)双向循环链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_SCNLIST_OPERATION_H

Operation.cpp
//
// Created by Today me on 2021/7/11.
//

#include "Operation.h"
/*-------------------1.链表----------------------*/
// (1)单向链表:
//  a.创建链表:
//  b.插入节点:1.头插     2.尾插    3.中间插
//  c.删除节点:1.头删     2.尾删    3.中间删
//  d.打印链表:

// (2)单向循环链表:

//  a.创建链表:
SCN *CreateHead() {
    SCN *pHead = new SCNode();
    pHead->pNext = pHead;       //注意:此处是单向循环链表所以自己指向自己,与单向链表不同
    HeadM;                      //设置HeadMark
    cout << "Enter a value of the ListHead[" << pHead->mark << "]:" << endl;
    cin >> pHead->date;         //键入头结点存储数据
    return pHead;
}

//  b.插入节点:1.头插     2.尾插    3.中间插
SCN *InsertHead(SCN *pHead) {
    SCN *pNTemp = pHead;
    int TpMark = pHead->mark;
    char ch = 'y';
    while ('y' == ch || 'Y' == ch) {
        SCN *newNode = new SCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
        newNode->mark = TpMark;      //设置newNode的mark
        cin >> newNode->date;        //键入存储的值
        newNode->pNext = pNTemp;     //使NewNode的尾指针pNext指向pHead[将NewNode插入pHead前]
        pHead->pNext = newNode;      //此处保证最开始的节点pHead的pNext始终指向真正的头newNode[构成循环——环结构]
        pNTemp = newNode;            //将NewNode赋值给pNTemp[前移指针pNTemp]
        cout << "Enter choice inserter(y/n):" << endl;
        cin >> ch;
    }
    //RegularMark(pHead);
    return pHead;
}

SCN *InsertTail(SCN *pHead) {
    SCN *pNTemp = pHead;
    char ch = 'Y';
    pNTemp = FindTail(pNTemp);      //调用FindTail找到尾节点指针,赋给pNTemp
    int TpMark = pNTemp->mark;      //记录尾节点Mark
    while (ch == 'y' || ch == 'Y') {
        SCN *newNode = new SCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
        newNode->mark = TpMark;     //写入TpMark到newNode Mark中
        cin >> newNode->date;
        pNTemp->pNext = newNode;    //将尾节点的pNext指针指向NewNode[链接NewNode到List尾部]
        newNode->pNext = pHead;     //此处保证最新的节点newNode的pNext始终指向真正的头pHead[构成循环——环结构]
        pNTemp = newNode;           //将NewNode赋给pNTemp[使pNTemp指向尾节点]
        cout << "Enter choice inserter(y/n):" << endl;
        cin >> ch;
    }
    //RegularMark(pHead);
    return pHead;
}

SCN *InsertMiddle(SCN *pHead, int pos) {
    SCN *pNTemp01 = pHead, *pNTemp02 = nullptr;
    pos--;
    char ch = 'y';
    //int count = 0;
    pNTemp01 = FindNode(pHead, pos);    // 找到插入节点的前一个节点pNTemp01
    pNTemp02 = pNTemp01->pNext;         // 找到应该插入的位置节点pNTemp02
    while (ch == 'y' || ch == 'Y') {
        SCN *newNode = new SCNode();
        //if (nullptr == newNode){perror("内存申请失败");exit(-1);}
        newNode->mark = pNTemp01->mark;
        newNode->mark++;
        cout << "Enter a value of the inserted node:" << endl;
        cin >> newNode->date;
        pNTemp01->pNext = newNode;      // 将newNode赋给pNTemp01->pNext[将newNode链接在pNTemp01后]
        newNode->pNext = pNTemp02;      // 将pNTemp02赋给newNode->pNext[将pNTemp02链接在newNode->pNext后]
        pNTemp01 = pNTemp01->pNext;     // 将pNTemp01后移一位指向newNode
        //while (nullptr != (pNTemp01 = pNTemp01->pNext))++pNTemp01->mark;
        cout << "Enter choice of inserter(y/n):" << endl;
        cin >> ch;
        //count++;
    }
    //while (nullptr != (pNTemp01 = pNTemp01->pNext))pNTemp01->mark += count;
    RegularMark(pHead);
    return pHead;
}

//  c.删除节点:1.头删     2.尾删    3.中间删
SCN *DeleteHead(SCN *pHead) {
    char ch = 'y';
    SCN *LTail = FindTail(pHead),*pNTemp = pHead;
    while ('y' == ch || 'Y' == ch) {
        pNTemp = pHead;         //暂存pHead
        pHead = pHead->pNext;   //将pHead指向下一个节点
        LTail->pNext = pHead;   //始终使尾节点LTail的pNext指向头结点pHead
        cout << "Enter choice of deleting head node (y/n):" << endl;
        cin >> ch;
        if (pNTemp!= LTail) {      //确保DisplayList函数正常调用
            DisplayList(pHead);
            delete pNTemp;        //释放内存
        } else {
            cout << "Can't remove the last node!" << endl;
            break;
        }
    }
    //RegularMark(pHead);
    return pHead;
}

SCN *DeleteTail(SCN *pHead) {     //(1)不断循环寻找最后节点删除
    //(1)
    char ch = 'y';
    unsigned int count = 0;
    SCN *pNTemp = pHead, *pNTemp01 = nullptr, *pNTemp02 = nullptr;
    RegularMark(pHead);
    while ('y' == ch || 'Y' == ch) {
        count = DisplayList(pNTemp);
        if (pHead == pNTemp01) {      //确保内存安全
            cout << "Can't remove the last node!" << endl;
            break;
        }
        pNTemp01 = FindNode(pNTemp, count - 2);     // 找到尾节点的前一个节点
        pNTemp02 = pNTemp01->pNext;                      // 暂存尾节点
        pNTemp01->pNext = pHead;                         // 使得原尾节点前一个节点变为尾节点且指向pHead
        delete pNTemp02;                                 // 释放原尾节点内存
        pNTemp02 = nullptr;                              // 避免pNTemp02野指针
        cout << "Enter choice of deleting tail node (y/n):" << endl;
        cin >> ch;
    }
    //RegularMark(pHead);
    return pHead;
}

SCN *DeleteMiddle(SCN *pHead, int pos) {
    SCN *pNTemp01 = pHead, *pNTemp02 = nullptr, *pNTemp03 = nullptr;
    pNTemp01 = FindNode(pNTemp01, pos - 2);     // 前节点指针
    pNTemp02 = pNTemp01->pNext;                      // 中结点指针
    pNTemp03 = pNTemp02->pNext;                      // 尾结点指针
    pNTemp01->pNext = pNTemp03;         // 前后链接
    delete pNTemp02;                    // 删除中间节点
    pNTemp02 = nullptr;                 // 避免pNTemp02野指针
    //RegularMark(pHead);
    return pHead;
}

//  d.打印链表:
unsigned int DisplayList(SCN *pHead) {
    unsigned int count = 0;
    SN *pNTemp = pHead;
    do {
        cout << "NODE[" << pHead->mark << "] = " << pHead->date << endl;
        count++;
    } while ((pHead = pHead->pNext) != pNTemp);
    return count;
}




main.cpp
#include "Structure.h"
#include "Operation.h"

int main() {
    SCN *pHead = nullptr;            //创建单向链表类型的头指针pHead,初始化为空指针nullptr
    pHead = CreateHead();           //创建头结点,pHead存储头结点的位置(存储头结点的位置)
//    pHead = InsertHead(pHead);      //调用头插
    pHead = InsertTail(pHead);      //调用尾插
//    pHead = InsertMiddle(pHead,2);      //调用中间插入
//    pHead = DeleteHead(pHead);               //调用头删
//    pHead = DeleteTail(pHead);               //调用尾删
    pHead = DeleteMiddle(pHead,2);      //调用中间删除[至少三个节点]
    int count = DisplayList(pHead);
    cout << "\nCount of list = " << count << "\nThe tail date of list = " << FindTail(pHead)->date << endl;
    delete pHead;       //释放pHead
    return 0;
}

测试结果如下图1.1.2:
在这里插入图片描述
图1.1.2 测试结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值