【数据结构】 循环双链表的基本操作 (C语言版)

这篇具有很好参考价值的文章主要介绍了【数据结构】 循环双链表的基本操作 (C语言版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、循环双链表

1、循环双链表的定义:

2、循环双链表的优缺点:

二、循环双链表的基本操作算法(C语言) 

  1、宏定义

 2、创建结构体

3、循环双链表的初始化 

4、循环双链表按位查找

5、循环双链表插入

6、循环双链表查找

7、循环双链表删除

8、求循环双链表长度

9、循环双链表清空

10、循环双链表销毁

11、头插法建立循环双链表

12、尾头插法建立循环双链表

13、输出链表元素

三、循环双链表的基本操作完整代码(C语言)

四、运行结果


一、循环双链表

1、循环双链表的定义:

循环双链表是一种特殊的双链表,其特点是尾节点的指针域指向头结点,形成一个环状结构。这种数据结构允许从链表的任意节点出发,通过后移操作,遍历整个循环双链表。

【数据结构】 循环双链表的基本操作 (C语言版),数据结构,链表,c语言

2、循环双链表的优缺点:

循环双链表的优点:

  1. 可以从任意节点出发,遍历整个链表,提高了遍历的灵活性。
  2. 在某些应用场景中,循环双链表可以提供更高的访问效率。

循环双链表的缺点:

  1. 插入和删除节点需要更多的时间来调整指针,因为需要维护链表的环状结构。
  2. 循环双链表的空间利用率相对较低,因为需要额外的指针来存储前驱和后继节点的信息。

二、循环双链表的基本操作算法(C语言) 

  1、宏定义
#define OK 1
#define ERROR 0

typedef char ElemType;
typedef int Status;
 2、创建结构体
/**定义一个具有前驱指针和后继指针的双链表的结构体**/
typedef struct DuLNode {
    ElemType data;  //数据域
    struct DuLNode *prior; //指向直接前驱
    struct DuLNode *next; //指向直接后继
    //    struct DuLNode *prior,*next;		//前驱指针和后继指针
} DuLNode, *DuLinkList; //前者强调这是结点,后者强调这是链表
3、循环双链表的初始化 
//循环双链表初始化
Status InitList(DuLinkList &head) {
    head = new DuLNode;
    head->prior = head;//循环双链表
    head->next = head;
    return OK;
}
4、循环双链表按位查找
//按位查找
DuLNode *GetElem(DuLinkList L, int i) {
    int j = 1;//因为有头结点,所以从1开始遍历
    if (i < 1) {//判断查找的位置是否合法
        printf("数值非法");
    }
    DuLNode *p = L->next;//初始化结点指针
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    return p;
}
5、循环双链表插入
//插入
Status ListInsert_Dul(DuLinkList &head, int i, ElemType e) {
   DuLinkList p = head;
   int j=0;
    while (p && (j<i-1)){
       p=p->next;
       j++;
   }
    if (!p || j > i-1){
        return ERROR;
   }
    //DuLinkList p = GetElem(head, i);
    if (!p) {
        return ERROR;
    }
    DuLNode *s = new DuLNode;
    s->data = e;
    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;
    p->prior = s;

    return OK;
}
6、循环双链表查找
//查找
int LocateLinkListElem(DuLinkList head, ElemType e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p != head && (p->data != e)) {//p != L p!=NULL
        p = p->next;
        j++;
    }
    if (p == head) { //p==L  !p<=>p==NULL
        return 0;
    }
    return j;
}
7、循环双链表删除
//删除
Status ListDelete_DuL(DuLinkList &head, int i, ElemType &e) {
    DuLinkList p=head;
    int j=0;
    while (p->next != head  && j <= i){  //p != L
        p=p->next;
        j++;
    }
    if (p->next == head){ //p==L
        return ERROR;
    }
    //调用按位查找函数
//    DuLinkList p = GetElem(head, i);
    if (!p) {
        return ERROR;
    }
    e = p->data;
    p->prior->next = p->next;
    p->next->prior = p->prior;
    delete p;
    return OK;
}
8、求循环双链表长度

//求双链表长度
Status GetLinkListLength(DuLinkList head) {
    DuLinkList p = head->next;
    int length = 0;
    while (p != head) {   //p!=NULL          //单链表不为空表时
        length++;
        p = p->next;
    }
    return length;
}
9、循环双链表清空
//清空
Status ClearList(DuLinkList &head) {
    DuLinkList p = head->next;
    DuLinkList q;
    while (p != head) { //p != L  p!=NULL
        q = p;
        p = p->next;
        delete q;
    }
    head->prior = head;
    head->next = head; //链表为空
    return OK;
}
10、循环双链表销毁
//销毁
Status DestroyList(DuLinkList &head) {

    DuLinkList p, q;//初始化两个指针,p用来free释放,q用来在p释放后将p指针指向下一个
    p = head->next;//删除带头链表头结点不删除
    q = p;
    while (p != head) {
        q = p->next;  //提前将q指向下一个
        delete p;    //释放p
        p = q;        //将p指向q所指向的下一个
    }
    head->next = NULL; //头结点指向NULL
    return OK;
    //printf("\n销毁成功\n");
}
11、头插法建立循环双链表
void CreateDLinkList_H(DuLinkList &head, int n) {
    InitList(head);
    for (int i = 0; i < n; i++) {
        DuLNode *p = new DuLNode;
        //scanf("%c",&p->data);
        p->data = getche();
        //cin >> p->data;
        p->next = head->next;
        if (head->next != NULL) {
            head->next->prior = p;
        }
        p->prior = head;
        head->next = p;
    }
}
12、尾头插法建立循环双链表
void CreateDoubleList_R(DuLinkList &head, int n) {
    InitList(head);
    DuLinkList r = head;  // 初始化 r 指针为头结点
    for (int i = 0; i < n; i++) {
        DuLNode *p = new DuLNode;
        //scanf("%c",&p->data);
        p->data = getche();
        //cin >> p->data;
        //p->next=NULL   p->next=head
        p->next = r->next;
        if (r->next != NULL) {
            r->next->prior = p;
        }
        p->prior = r;
        r->next = p;
        r = p;  // r 指向新插入的节点,更新尾指针
    }
    r->next = head;  // 将尾节点的 next 指针指向头结点,形成循环
}
13、输出链表元素
//输出链表元素
void printLinkList(DuLinkList head) {
    DuLinkList p = head->next;
    while (p != head) { //p != L
        printf("%c", p->data);
        p = p->next;
    }
    printf("\n");
}

三、循环双链表的基本操作完整代码(C语言)

#include <stdio.h>
#include <conio.h>//getche()

#define OK 1
#define ERROR 0

typedef char ElemType;
typedef int Status;

/**定义一个具有前驱指针和后继指针的双链表的结构体**/
typedef struct DuLNode {
    ElemType data;  //数据域
    struct DuLNode *prior; //指向直接前驱
    struct DuLNode *next; //指向直接后继
    //    struct DuLNode *prior,*next;		//前驱指针和后继指针
} DuLNode, *DuLinkList; //前者强调这是结点,后者强调这是链表


//双链表初始化
Status InitList(DuLinkList &head) {
    head = new DuLNode;
    head->prior = head;//循环双链表
    head->next = head;
//    head->prior = NULL;
//    head->next = NULL;
    return OK;
}


//功能菜单
int choice() {
    printf("==================================\n");
    printf("         双链表操作功能菜单        \n");
    printf("1、插入元素  2、查询表长  3、按位查找\n");
    printf("4、按值查找  5、删除元素  6、销毁链表\n");
    printf("7、清空链表  8、批量插入  9、链表元素\n");
    printf("10、头插法创建双链表11、尾插法创建双链表\n");
    printf("==================================\n");
    return 0;
}

//按位查找
DuLNode *GetElem(DuLinkList L, int i) {
    int j = 1;//因为有头结点,所以从1开始遍历
    if (i < 1) {//判断查找的位置是否合法
        printf("数值非法");
    }
    DuLNode *p = L->next;//初始化结点指针
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    return p;
}

//插入
Status ListInsert_Dul(DuLinkList &head, int i, ElemType e) {
//    DuLinkList p = head;
//    int j=0;
//    while (p && (j<i-1)){
//        p=p->next;
//        j++;
//    }
//    if (!p || j > i-1){
//        return ERROR;
//    }
    DuLinkList p = GetElem(head, i);
    if (!p) {
        return ERROR;
    }
    DuLNode *s = new DuLNode;
    s->data = e;
    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;
    p->prior = s;

    return OK;
}

//查找
int LocateLinkListElem(DuLinkList head, ElemType e) {
    DuLinkList p = head->next;
    int j = 1;
    while (p != head && (p->data != e)) {//p != L p!=NULL
        p = p->next;
        j++;
    }
    if (p == head) { //p==L  !p<=>p==NULL
        return 0;
    }
    return j;
}

//删除
Status ListDelete_DuL(DuLinkList &head, int i, ElemType &e) {
//    DuLinkList p=head;
//    int j=0;
//    while (p->next != head  && j <= i){  //p != L
//        p=p->next;
//        j++;
//    }
//    if (p->next == head){ //p==L
//        return ERROR;
//    }
    //调用按位查找函数
    DuLinkList p = GetElem(head, i);
    if (!p) {
        return ERROR;
    }
    e = p->data;
    p->prior->next = p->next;
    p->next->prior = p->prior;
    delete p;
    return OK;
}

//求双链表长度
Status GetLinkListLength(DuLinkList head) {
    DuLinkList p = head->next;
    int length = 0;
    while (p != head) {   //p!=NULL          //单链表不为空表时
        length++;
        p = p->next;
    }
    return length;
}


//清空
Status ClearList(DuLinkList &head) {
    DuLinkList p = head->next;
    DuLinkList q;
    while (p != head) { //p != L  p!=NULL
        q = p;
        p = p->next;
        delete q;
    }
    head->prior = head;
    head->next = head; //链表为空
    return OK;
}

//销毁
Status DestroyList(DuLinkList &head) {

    DuLinkList p, q;//初始化两个指针,p用来free释放,q用来在p释放后将p指针指向下一个
    p = head->next;//删除带头链表头结点不删除
    q = p;
    while (p != head) {
        q = p->next;  //提前将q指向下一个
        delete p;    //释放p
        p = q;        //将p指向q所指向的下一个
    }
    head->next = NULL; //头结点指向NULL
    return OK;
    //printf("\n销毁成功\n");
}

//头插法创建循环双链表
void CreateDLinkList_H(DuLinkList &head, int n) {
    InitList(head);
    for (int i = 0; i < n; i++) {
        DuLNode *p = new DuLNode;
        //scanf("%c",&p->data);
        p->data = getche();
        //cin >> p->data;
        p->next = head->next;
        if (head->next != NULL) {
            head->next->prior = p;
        }
        p->prior = head;
        head->next = p;
    }
}

//尾插法创建循环双链表
void CreateDoubleList_R(DuLinkList &head, int n) {
    InitList(head);
    DuLinkList r = head;  // 初始化 r 指针为头结点
    for (int i = 0; i < n; i++) {
        DuLNode *p = new DuLNode;
        //scanf("%c",&p->data);
        p->data = getche();
        //cin >> p->data;
        //p->next=NULL   p->next=head
        p->next = r->next;
        if (r->next != NULL) {
            r->next->prior = p;
        }
        p->prior = r;
        r->next = p;
        r = p;  // r 指向新插入的节点,更新尾指针
    }
    r->next = head;  // 将尾节点的 next 指针指向头结点,形成循环
}

//输出链表元素
void printLinkList(DuLinkList head) {
    DuLinkList p = head->next;
    while (p != head) { //p != L
        printf("%c", p->data);
        p = p->next;
    }
    printf("\n");
}

int main() {

    DuLinkList list;

    printf("双链表正在初始化....\n");
    int InitStatus = InitList(list);
    if (InitStatus == OK) {
        printf("双链表初始化成功!\n");
    } else {
        printf("双链表初始化失败!\n");
    }

    choice();

    while (1) {
        int flag;
        printf("请输入所需的功能编号:\n");
        scanf("%d", &flag);

        switch (flag) {//通过开关进行功能选择
            case 1: {//插入元素
                //ListInsert_Dul(list,1,'a');
                int insertIndex;
                ElemType inserElem;
                printf("请输入插入元素位置及插入元素(请在英文状态下输入例如:1,a): \n");
                scanf("%d,%c", &insertIndex, &inserElem);
                Status InsertS = ListInsert_Dul(list, insertIndex, inserElem);
                if (InsertS == OK) {
                    printf("向双循环链表%d个位置,插入元素为%c成功!\n\n", insertIndex, inserElem);
                } else {
                    printf("向双循环链表插入元素失败!\n\n");
                }
            }
                break;
            case 2: {//求单链表的长度
                int length = GetLinkListLength(list);
                printf("循环双链表的长度为:%d。 \n\n", length);
            }
                break;
            case 3: {//取值
                Status GetIndex;
                printf("请输入需要查询的元素的位置:\n");
                scanf("%d", &GetIndex);
                DuLinkList GetStatus = GetElem(list, GetIndex);
                ElemType GetElem = GetStatus->data;
                if (GetStatus != NULL) {
                    printf("从双链表中获取第%d位置元素成功,所获取到的元素为:%c。\n\n", GetIndex, GetElem);
                } else {
                    printf("从双链表中获取第%d位置元素失败!\n\n", GetIndex);
                }
            }
                break;
            case 4: {//查找
                ElemType LocateElem;
                printf("请输入想要查找元素:\n");
                getchar();    //用于接收回车
                scanf("%c", &LocateElem);
                Status LocateIndex = LocateLinkListElem(list, LocateElem);
                if (LocateIndex > 0) {
                    printf("从双链表中查找元素%c成功,它在循环链表中的位置为第%d个!\n\n", LocateElem, LocateIndex);
                } else {
                    printf("从双链表中查找元素%c失败!\n\n", LocateElem);
                }
            }
                break;
            case 5: {//删除
                //ListDelete_DuL(list,1);
                Status DeleteIndex;
                printf("请输入想要删除元素的位置:\n");
                scanf("%d", &DeleteIndex);
                ElemType DeleteElem;
                ElemType DeleteStatus = ListDelete_DuL(list, DeleteIndex, DeleteElem);
                if (DeleteStatus == OK) {
                    printf("删除双链表第%d个位置的元素成功,删除的元素为:%c。\n\n", DeleteIndex, DeleteElem);
                } else {
                    printf("删除双链表第%d个位置的元素失败!\n\n", DeleteIndex);
                }
            }
                break;
            case 6: {//销毁
                Status DestoryStatus = DestroyList(list);
                if (DestoryStatus == OK) {
                    printf("双环链表销毁成功!\n\n");
                } else {
                    printf("双链表销毁失败!\n\n");
                }
            }
                break;
            case 7: {//清空
                Status ClearStatus = ClearList(list);
                if (ClearStatus == OK) {
                    printf("双链表清空成功!\n\n");
                } else {
                    printf("双链表清空失败!\n\n");
                }
            }
                break;
            case 8: {//批量插入
                int on;
                printf("请输入想要插入的元素个数:\n");
                scanf("%d", &on);
                ElemType array[on];
                for (int i = 1; i <= on; i++) {
                    getchar();
                    printf("向双链表第%d个位置插入元素为:", (i));
                    scanf("%c", &array[i]);
                }

                for (int i = 1; i <= on; i++) {
                    Status InsertStatus = ListInsert_Dul(list, i, array[i]);
                    if (InsertStatus == OK) {
                        printf("向双链表第%d个位置插入元素%c成功!\n", i, array[i]);
                    } else {
                        printf("向双链表第%d个位置插入元素%c失败!\n", i, array[i]);
                    }
                }
            }
                break;
            case 9: {//输出链表元素
                printLinkList(list);
            }
                break;
            case 10: {//头插法创建双链表
                //getchar();
                DuLinkList L;
                printf("请输入五个字符:\n");
                CreateDLinkList_H(L, 5);
                int length = GetLinkListLength(L);
                printf("\n循环双链表的长度为:%d。 \n", length);
                printf("循环双链表的元素为:");
                printLinkList(L);
                printf("\n");
            }
                break;
            case 11: {//尾插法创建双链表
                DuLinkList L;
                printf("请输入五个字符:\n");
                CreateDoubleList_R(L, 5);
                int length = GetLinkListLength(L);
                printf("\n循环双链表的长度为:%d。 \n", length);
                printf("循环双链表的元素为:");
                printLinkList(L);
                printf("\n");
            }
                break;
            default: {
                printf("输入错误,无此功能,请检查输入:\n\n");
            }
        }
    }

    return 1;

}

四、运行结果

【数据结构】 循环双链表的基本操作 (C语言版),数据结构,链表,c语言

【数据结构】 循环双链表的基本操作 (C语言版),数据结构,链表,c语言

【数据结构】 循环双链表的基本操作 (C语言版),数据结构,链表,c语言 

 文章来源地址https://www.toymoban.com/news/detail-815567.html

到了这里,关于【数据结构】 循环双链表的基本操作 (C语言版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构 2.1 线性表的定义和基本操作

    数据结构三要素——逻辑结构、数据的运算、存储结构(物理结构) 线性表是具有 相同数据类型 的n(n=0)个数据元素的 有限序列 ,其中n为表长,当n=0时,线性表是一个空表。 每个数据元素所占空间一样大,有次序。 几个概念 1.ai是线性表中的第i个 i表示元素线性表中的

    2024年02月07日
    浏览(53)
  • c语言数据结构——链表的实现及其基本操作

    顺序表的问题及思考 问题: 中间/头部的插入删除,时间复杂度为O(N) 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插

    2023年04月09日
    浏览(85)
  • 【数据结构】单链表的基本操作 (C语言版)

    目录 一、单链表 1、单链表的定义: 2、单链表的优缺点: 二、单链表的基本操作算法(C语言) 1、宏定义 2、创建结构体 3、初始化 4、插入 4、求长度 5、清空 6、销毁  7、取值 8、查找 9、删除 10、头插法创建单链表 11、尾插法创建单链表 三、单链表的全部代码(C语言)

    2024年01月22日
    浏览(59)
  • 【数据结构】C语言实现单链表的基本操作

    大家好,很高兴又和大家见面啦!!! 在上一篇中,我们详细介绍了单链表的两种创建方式——头插法与尾插法,相信大家现在对这两种方式都已经掌握了。今天咱们将继续介绍单链表的基本操作——查找、插入与删除。在开始今天的内容之前,我们先通过尾插法创建一个单

    2024年02月03日
    浏览(65)
  • 数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(61)
  • 数据结构 线性表的定义和基本操作(以顺序表为例)

    名人说:一花独放不是春,百花齐放花满园。——《增广贤文》 作者:Code_流苏(CSDN) (一个喜欢古诗词和编程的Coder😊) 以下代码个人分享出来,仅供学习交流,且仅在CSDN平台发布,未经授权禁止二次转发。 〇、线性表是什么? 1、定义 线性表 是具有 相同数据类型 的 n(

    2024年02月12日
    浏览(62)
  • 数据结构(C语言实现)——顺序表的介绍及基本操作的实现

    今天我们来学习数据结构中的线性表,本文主要介绍一种常见的线性表——顺序表。 本文着重介绍顺序表的概念以及顺序表各种基本操作的实现过程(C语言实现),以后会更新更多的数据结构,觉得有用的朋友可以三连关注一波,一起学习。 线性表(linear list)是n个具有相

    2023年04月13日
    浏览(52)
  • 【数据结构】顺序表的实现及基本操作完整代码(C语言实现)

    顺序表:逻辑上相邻的数据元素,其物理次序也是相邻的 这里之所以要把int分别创建新名字为SqlElemType和Status,是因为实际应用时数据的类型不一定是int型,这样设置方便修改元素类型,提高代码适用性。 LocateElem的时间复杂度为O(n) InsertSq的时间复杂度为O(n) DeleteSq的时间

    2024年04月12日
    浏览(50)
  • C语言---数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(69)
  • 数据结构-线性表的顺序表基本操作代码实现(超级详细清晰 C++实现)

    顺序表是用一段 物理地址连续的存储单元 依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。 顺序表: 可动态增长的数组,要求数据是连续存储的 特点: 随机访问 顺序既可以 静态分配 ,也可以 动态分配 。在静态分配时,由于数组

    2024年02月07日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包