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

文章目录

总结归纳

  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; // 检查头结点的后继结点
}
上一篇:南昌大学-计算计-2020-2021-2学期-算法重点


下一篇:双向链表及有关操作(C语言)