单向循环链表:
数据结构示意图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 测试结果