ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ 循环双链表(带头结点)

2021-06-03 16:55:06  阅读:247  来源: 互联网

标签:结点 return C++ next prior DLinkList 双链 DNode


文章目录

总结归纳

  1. 在 InsertPriorNode 函数(前插操作)中,如果想在表尾处插入结点,则无法进行,需要特殊处理,比较简单,这里没有写出;同时,也可以使用 InsertNextNode 函数(后插操作)来实现。
  2. 循环双链表的实现与循环单链表大同小异,甚至还更为简洁。由于可以快速找到指定结点的前驱结点,所以很多对头结点、尾节点的插入和删除操作就不用特殊处理。
  3. 当然,循环双链表要付出一定的内存代价。

代码实现

/*
循环双链表(带头结点)
*/

#include <iostream>
#include <string>

using namespace std;

struct DNode {
    int data;     // 数据域
    DNode *prior; // 前驱结点
    DNode *next;  // 后继结点
};

typedef DNode DNode;      // DNode是一个循环双链表的结点
typedef DNode *DLinkList; // LinkList是一个循环双链表

// 初始化循环双链表
void InitList(DLinkList &L) {
    L = new DNode;
    // L = (DNode *)malloc(sizeof(DNode));
    L->next = L;
    L->prior = L;
}

// 判断循环双链表是否为空
bool Empty(DLinkList &L) {
    if (L->next == L) {
        return true;
    } else {
        return false;
    }
}

// 获取循环双链表长度
int GetLength(DLinkList &L) {
    DNode *p = L->next;
    int length = 0;
    while (p != L) {
        p = p->next;
        length++;
    }
    return length;
}

// 头插法建立循环双链表
DLinkList DList_HeadInsert(DLinkList &L) {
    int e;
    cin >> e;
    while (e != 9999) {
        if (L->next == L) { // 第一次插入时要特殊处理
            DNode *s = new DNode;
            s->data = e;
            s->next = L->next;
            L->next = s;
            s->prior = L;
            L->prior = s;
            cin >> e;
        } else {
            DNode *s = new DNode;
            s->data = e;
            s->next = L->next;
            L->next->prior = s;
            L->next = s;
            s->prior = L;
            cin >> e;
        }
    }
    return L;
}

// 尾插法建立循环双链表
DLinkList DList_TailInsert(DLinkList &L) {
    DNode *r = L; // r为尾指针
    int e;
    cin >> e;
    while (e != 9999) {
        DNode *s = new DNode;
        s->next = r->next;
        s->prior = r;
        s->data = e;
        r->next = s;
        L->prior = s;
        r = s; // 更新尾指针
        cin >> e;
    }
    return L;
}

// 按位查找:查找第i个结点
DNode *GetElem(DLinkList &L, int i) {
    if (i < 0) {
        return NULL;
    }
    DNode *p = L;
    int j = 0;
    while (p->next != L && j != i) {
        p = p->next;
        j++;
    }
    return p;
}

// 按值查找:查找数据域为e的结点
DNode *GetLNode(DLinkList &L, int e) {
    DNode *p = L->next;
    while (p != L && p->data != e) {
        p = p->next;
    }
    return p;
}

// 前插操作:在p结点前插入数据e
bool InsertPriorNode(DLinkList &L, DNode *p, int e) {
    if (p == L) { // 在头结点前插入
        return false;
    }
    DNode *s = new DNode;
    s->next = p;
    s->prior = p->prior;
    s->data = e;
    p->prior->next = s;
    p->prior = s;
    return true;
}

// 后插操作:在p结点后插入数据e
bool InsertNextNode(DLinkList &L, DNode *p, int e) {
    if (p == L) {
        return false;
    }
    DNode *s = new DNode;
    s->next = p->next;
    p->next->prior = s;
    s->data = e;
    p->next = s;
    s->prior = p;
    return true;
}

// 按位序插入
bool DListInsert(DLinkList &L, int i, int e) {
    if (i < 1) {
        return false;
    }
    DNode *p = GetElem(L, i - 1); // 找到前一个结点
    InsertNextNode(L, p, e);      // 后插法
    /*  // 前插法,实现同样效果
    // DNode *p = GetElem(L, i);
    // InsertPriorNode(L, p, e);
    */
    return true;
}

// 删除p结点的后继结点
bool DeleteNextDNode(DLinkList &L, DNode *p) {
    if (p->next == L) { // p是最后一个结点
        return false;
    }
    DNode *s = new DNode;
    s = p->next;
    p->next = s->next;
    s->next->prior = p;
    delete s;
    return true;
}

// 删除当前结点
bool DeleteNode(DLinkList &L, DNode *p) {
    if (p == L) {
        return false;
    }
    p->prior->next = p->next;
    p->next->prior = p->prior;
    delete p;
    return true;
}

// 按位序删除
bool DListDelte(DLinkList &L, int i, int &e) {
    if (i < 1) {
        return false;
    }
    DNode *p = new DNode;
    p = GetElem(L, i);
    e = p->data;
    DeleteNode(L, p); // 删除当前结点
    /*  // 删除前一个结点的后继结点,达到同样效果
    DNode *p = new DNode;
    p = GetElem(L, i - 1);
    e = p->next->data;
    DeleteNextDNode(L, p);
    */
    return true;
}

// 遍历单链表
void TraverseDList(DLinkList &L) {
    DNode *p = L->next;
    while (p != L) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

int main() {
    DLinkList L;
    InitList(L);
    cout << Empty(L) << endl;

    // L = DList_HeadInsert(L);  // 头插法
    L = DList_TailInsert(L); // 尾插法
    TraverseDList(L);

    DListInsert(L, 3, 5244);
    TraverseDList(L);

    int e = -1;
    DListDelte(L, 1, e);
    cout << "被删除的值:" << e << endl;
    TraverseDList(L);

    cout << "尾节点:" << L->prior->data << endl; // 检查尾节点
    cout << "头结点的后继结点:" << L->next->next->data << endl; // 检查头结点的后继结点
}

标签:结点,return,C++,next,prior,DLinkList,双链,DNode
来源: https://blog.51cto.com/u_15251606/2852397

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有