【数据结构】其三:双向(循环)链表——2022/01/02

【数据结构】其三:双向(循环)链表——2022/01/02

新年新气象……我感觉又行了。回望过去,真是经历了坎坷的一年,但是也好歹算是有惊无险地过去了。希望今年能一切顺利的进行下去。😆

今日份代码——双向循环链表:
#include <stdio.h>
#include <stdlib.h>

/**
 * 注释:
 * 项目建立时间:2022/01/01
 * 项目名称:双向(循环)链表
 * 操作集:构造表、基本查找(按位/值查找)、删除、插入、求表长;
 * 
 * 
 */

typedef int DataType;
typedef struct dunode
{
    DataType data;
    struct dunode *prior;
    struct dunode *next;
} DuLinkList;

/* 初始化双向(循环)链表 */
DuLinkList *InitDList()
{
    DuLinkList *head;
    head = (DuLinkList *)malloc(sizeof(DuLinkList));
    head->next = head;

    return head;
}

/* 创建双向(循环)链表 */
void CreateDList(DuLinkList *head, int n)
{
    DuLinkList *s, *last;
    last = head;

    printf("请输入%d个元素:\n", n);
    for (int i = 0; i < n; i++)
    {
        s = (DuLinkList *)malloc(sizeof(DuLinkList));
        scanf("%d", &s->data);
        s->prior = last;
        s->next = head;
        last->next = s;
        head->prior = s;
        last = s;
    }
    printf("建立尾插法双向(循环)链表成功!\n");
}

/* 插入元素 */
void DuIns_Elem(DuLinkList *head, DataType x, int i)
{
    DuLinkList *s, *p;
    p = head;
    int j = 0;

    if (i == 1)
    {
        s = (DuLinkList *)malloc(sizeof(DuLinkList));
        s->data = x;
        s->prior = p;
        s->next = p->next;
        p->next->prior = s;
        p->next = s;

        printf("插入元素成功!\n");
        return;
    }

    while (p->next != head && j < i - 1)
    {
        p = p->next;
        j++;
    }

    if (p != head)
    {
        s = (DuLinkList *)malloc(sizeof(DuLinkList));
        s->data = x;
        s->prior = p;
        s->next = p->next;
        p->next->prior = s;
        p->next = s;

        printf("插入元素成功!\n");
    }
    else
    {
        printf("插入位置越界,插入失败!\n");
    }
}

/* 删除元素 */
void DuDel_Elem(DuLinkList *head, int i)
{
    DataType x;
    int j = 0;
    DuLinkList *s, *p;
    p = head;

    while (p->next != head && j < i - 1)
    {
        p = p->next;
        j++;
    }

    if (p->next != head && j == i - 1)
    {
        s = p->next;
        x = s->data;
        p->next = s->next;
        s->next->prior = p;

        free(s);
        printf("删除第%d位,上的%d元素成功!\n", i, x);
    }
    else
    {
        printf("删除节点位置错误,删除失败!\n");
    }
}

/* 循环输出表中元素 */
void DispDList(DuLinkList *head)
{
    DuLinkList *p;
    p = head->next;
    while (p != head)
    {
        printf("%d\t", p->data);
        p = p->next;
    }
    printf("\n");
}

/* 获取链表表长 */
int LengthDList(DuLinkList *head)
{
    DuLinkList *p = head->next;
    int j = 0;
    while (p != head)
    {
        p = p->next;
        j++;
    }
    printf("表长为:\t%d\n", j);
    return j;
}

/* 按值查找 */
void LocDValue(DuLinkList *head, DataType x)
{
    int j = 1;
    DuLinkList *p;
    p = head->next;

    while (p != head && p->data != x)
    {
        p = p->next;
        j++;
    }

    if (p != head)
    {
        printf("在表的第%d位,找到值为%d的结点!\n", j, x);
    }
    else
    {
        printf("未找到值为%d的结点!\n", x);
    }
}

/* 按位查找 */
void LocDNum(DuLinkList *head, int i)
{
    DuLinkList *p;
    p = head;
    int j = 0;

    if (i > LengthDList(head))
    {
        printf("输入位置超出表长!\n");
        return;
    }

    while (p->next != head && j < i)
    {
        p = p->next;
        j++;
    }

    if (j == i)
    {
        printf("在第%d位上的元素值为%d!\n", i, p->data);
    }
}

void menu()
{
    printf("\t链表的各种操作:\n");
    printf("==============================\n");
    printf("\t1----建立双向(循环)链表\n");
    printf("\t2----插入元素\n");
    printf("\t3----删除元素\n");
    printf("\t4----按位置查找元素\n");
    printf("\t5----按元素值查找在表中的位置\n");
    printf("\t6----求链表的长度并输出表中元素\n");
    printf("\t0----退出\n");
    printf("==============================\n");
}

int main()
{
    DuLinkList *head;
    head = (DuLinkList *)malloc(sizeof(DuLinkList));
    DataType x;
    int n, num, i;
    char flag = 'y';

    while (flag == 'y')
    {
        menu();
        printf("请输入菜单号:\n");
        scanf("%d", &num);

        if (flag == 'n')
        {
            break;
        }

        switch (num)
        {
        case 0:
            flag = 'n';
            break;
        case 1:
            printf("这是一个双向(循环)链表!\n");
            head = InitDList();

            printf("请输入链表元素数量:\n");
            scanf("%d", &n);

            CreateDList(head, n);
            DispDList(head);
            break;
        case 2:
            printf("请输入您想插入的元素的位置:\t");
            scanf("%d", &i);
            printf("请输入您想插入的值:\n");
            scanf("%d", &x);
            DuIns_Elem(head, x, i);
            DispDList(head);

            break;
        case 3:
            printf("请输入您想删除的元素的位置:\t");
            scanf("%d", &i);

            DuDel_Elem(head, i);
            DispDList(head);
            break;
        case 4:
            printf("请输入您想查询的位置:\t");
            scanf("%d", &i);
            LocDNum(head, i);
            DispDList(head);

            break;
        case 5:
            printf("请输入您想查询的值:\t");
            scanf("%d", &i);
            LocDValue(head, i);
            DispDList(head);
            break;
        case 6:
            LengthDList(head);
            DispDList(head);
            break;
        default:
            printf("菜单号错误!\n请输入0-6的值!!\n");
            break;
        }
    }
}



有点小问题:那个插入方法,只能插入位置大于等于2 的位置……之后看看有没有必要改罢。 😌 (这个问题已解决,插入位置要为1的时候,需要单独进行判断。)
虽然双向循环链表并不难,之前也有学过,但是现在重新捡起来,敲一敲——发现理解还是有问题的。还是需要多加实践才行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值