严蔚敏数据结构c++实现双向循环链表

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;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值