Node.h头文件
#pragma once
typedef int ElemType;
// 线性链表声明
typedef struct Node
{
Node* next; // 指项下一个结点的指针
Node* prior; //指向前一个节点的指针
ElemType data; // 数据
} *DoubleLinkList;
DoubleLinkList.h头文件
#pragma once
#define OK 1 // 操作成功
#define ERROR 0 // 操作失败
typedef int Status; // 返回操作状态
// 双向循环链表的初始化,空表但已经分配地址空间
Status InitLinkList(DoubleLinkList& L)
{
L = new Node; // 申请一个Node
L->next = L;
L->prior = L;
return OK;
}
// 求取双向循环链表表长
int Length(DoubleLinkList L)
{
int j = 0;
Node* p = L;
while (p->next != L) // 判断是否指回表头
{
j++;
p = p->next;
}
return j;
}
// 销毁双向循环链表
Status Destory(DoubleLinkList &L)
{
int count = Length(L) + 1; // 对于双向循环链表来说利用指针不方便结束循环,因此用计数来代替,加上头结点一共有length+1个结点
Node* p;
while (count--) // 每释放一个结点就将计数器减1
{
p = L;
L = L->next;
delete p;
}
L = NULL;
return OK;
}
// 清空双向循环链表
Status Clear(DoubleLinkList L)
{
Node* p = L->next; // 此处从首元节点开始清空,不需要计数器
Node* q;
while (p != L) // 当p指向头结点时循环结束
{
q = p;
p = p->next;
delete q;
}
L->next = L;
L->prior = L;
return OK;
}
//判断双向循环链表是否为空
bool isEmpty(DoubleLinkList L)
{
if (L->next == L)
{
return true;
}
else
{
return false;
}
}
// 获取指向指定节点处的指针
Node * GetElemPtr(DoubleLinkList L, int i) {
if (i == 0) {
return L;
}
// 这里有一点需要注意的是i的取值可以为0,此时直接返回头结点的指针;
Node* p = L->next;
int j = 1;
while (p != L && j<i) {
p = p -> next;
j++;
}
if (p==L || j > i) {
return NULL;
}
return p;
}
// 获取第i个元素
Status GetElem(DoubleLinkList L, int i, ElemType& e)
{
if(i<1 || i>Length(L)){
// 确保获取元素的位置是合法的
return ERROR;
}
Node* p = GetElemPtr(L, i);
e = p->data;
return OK;
}
// 改变第i个元素的data
Status SetElem(DoubleLinkList L, int i, ElemType e)
{
if (i<1 || i>Length(L)) {
// 确保修改元素的位置是合法的
return ERROR;
}
Node* p = GetElemPtr(L, i);
p->data = e;
return OK;
}
// 按值查找(返回地址)
Node* Inquire_P(DoubleLinkList L, ElemType e)
{
Node* p = L->next;
while (p != L && p->data!= e)
{
p = p->next;
}
// 首先要判断是否含有目标值e,如果有p最终不会等于L
if (p != L) {
return p;
}
else {
return NULL;
}
}
// 按值查找(返回位置)
int Inquire_N(DoubleLinkList L, ElemType e)
{
Node* p = L->next;
int j = 1;
while (p != L)
{
if (p->data == e)
{
return j;
}
p = p->next;
j++;
}
return -1; // 返回-1表示查找失败
}
// 在第i个结点前插入一个值为e的新结点
Status Insert(DoubleLinkList L, int i, ElemType e)
{
if (i<1 || i >Length(L) + 1) {
return ERROR;
}
Node* p = GetElemPtr(L, i-1);
Node* s= new Node;
s->data = e;
s->next = p->next;
s->prior = p;
s->next->prior = s;
p->next = s;
return OK;
}
// 双向链表的删除(不含返回值)
Status Delete(DoubleLinkList L, int i)
{
if (i<1 || i >Length(L)) {
return ERROR;
}
Node* p = GetElemPtr(L, i);
p->prior->next = p->next;
p->next->prior = p->prior;
delete p;
return OK;
}
/*
// 双向链表的删除(含返回值)
Status Delete(DoubleLinkList L, int i, ElemType& e)
{
if (i<1 || i >Length(L)) {
return ERROR;
}
Node* p = GetElemPtr(L, i);
p->prior->next = p->next;
p->next->prior = p->prior;
delete p;
return OK;
}
*/
// 头插法
void CreatList_H(DoubleLinkList& L, int n)
{
L = new Node;
L->next = L;
L->prior = L;
while(n--)
{
ElemType e;
cin >> e;
Insert(L, 1, e); // 直接调用insert
}
}
// 尾插法
void CreatList_R(DoubleLinkList& L, int n)
{
L = new Node;
L->next = L;
L->prior = L;
int count = 0;
while (n--)
{
ElemType e;
cin >> e;
Insert(L,++count, e);
}
}
// 对于双向循环链表来说倒置没有太多的意义
void Reverse_NUM(DoubleLinkList& L)
{
ElemType a, b;
int length = Length(L);
for (int i = 1; i <= length / 2; i++)
{
GetElem(L, i, a);
GetElem(L, length - i + 1, b);
SetElem(L, i, b);
SetElem(L, length - i + 1, a);
}
}
// 可以思考如何通过指针来实现双向链表的转置
// 遍历所有元素
void Traverse(DoubleLinkList L)
{
Node* p = L->next;
while (p != L)
{
cout << p->data<< " ";
p = p->next;
}
cout << endl;
}
测试文件main.cpp
#include<iostream>
#include<string>
using namespace std;
#include"Node.h"
#include"DoubleLinkList.h"
int main() {
DoubleLinkList L;
InitLinkList(L);
CreatList_H(L, 3);
cout << "------------------------------------" << endl;
ElemType a = 100;
Insert(L, 1, a);
Insert(L, Length(L), a + 100);
Insert(L, Length(L) + 1, a + 200);
Traverse(L);
cout << "------------------------------------" << endl;
Delete(L, Length(L));
Delete(L, 1);
Traverse(L);
cout << "---------------------------" << endl;
Reverse_NUM(L);
Traverse(L);
cout << "---------------------------------" << endl;
return 0;
}