【数据结构】其三:双向(循环)链表——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的时候,需要单独进行判断。)
虽然双向循环链表并不难,之前也有学过,但是现在重新捡起来,敲一敲——发现理解还是有问题的。还是需要多加实践才行。