LoopDLink.cpp 源码
1. 头文件包含
#include <stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<time.h>
typedef int ElemType; // 元素类型
typedef int Status; // 返回类型
#define OK 1 // 函数运行成功返回值
#define ERROR 0 // 函数运行失败返回值
typedef struct Node
{
struct Node *prior; // 指向前一结点的指针
ElemType date; // 结点元素
struct Node *next; // 指向后一结点的指针
}Node, *LoopDList;
2. 创建循环双链表
/*
* 循环双链表的创建
*/
Status CreatList(LoopDList &L, int *arr, int n)
{
int i;
L = (LoopDList)malloc(sizeof(Node)); // 创建头结点
L->next = L;
L->prior = L;
LoopDList s,p; // s用于开辟新结点,p指向表尾
p = L; // 指向表尾结点
for(i = 0; i < n; i++)
{
s = (LoopDList)malloc(sizeof(Node)); // 开辟新结点
s->date = arr[i]; // 为新结点赋值
p->next = s; // 让表尾结点的后继结点指向新结点
s->prior = p; // 让新结点的前驱结点指向p
p = s; // 表尾结点指针后移
}
p->next = L; // 使表尾结点的后继指针指向头结点
L->prior = p; // 头指针的前驱结点指向表尾结点
return OK;
}
3. 插入操作
/*
* 循环双向链表的插入操作
*/
Status LoopInsert(LoopDList &L, int i, ElemType e)
{
int j = 1; // 计数器,记录当前位置
LoopDList p = L; // 指向L,此种写法便于对当前结点的上一结点进行操作
LoopDList s; // 用于创建新结点
while(p->next != L && j < i)
{
p = p->next; // 指针后移
j++; // 计数器加1
}
if(p->next == L || j > i) // 判空,判位置索引不合理
return ERROR;
s = (LoopDList)malloc(sizeof(Node)); // 开辟新结点s
s->date = e; // 为s的数据域赋值
s->prior = p->prior;
s->next = p;
p->prior->next = s;
p->prior = s;
#if 0
p->next->prior= s; // 使插入结点后的下一结点的前驱指向s
s->next = p->next; // 使s的后继结点等于p的后继结点
s->prior= p; // 使s的前驱结点等于p
p->next = s; // 使p得后继结点等于s
#endif
return OK;
}
4. 删除操作
/*
* 循环双向链表的删除操作
* p = *L,循环体中用p->next做条件
* 这种写法便于对当前结点的前一结点操作,插入、删除、修改操作使用这种形式
*/
Status DelList(LoopDList &L, int i, ElemType *e)
{
int j = 1; // 记录当前位置
LoopDList p = L; // 指向链表
LoopDList s; // 用于释放要删除的结点
while(p->next != L && j < i) // 判非空 判索引位置有效
{
p = p->next; // 指针后移
j++; // 计数器加1
}
if(p->next == L || j > i) // 判空,判索引位置无效
return ERROR;
s = p->next; // 使s指向p
*e = s->date; // 将要删除的结点数据赋值给e
p->next = s->next; // 使p的后继结点等于r的后继结点
s->next->prior = p; // 使s的后继的前驱结点等于p
free(s); // 释放s结点
return OK;
}
5. 查找操作
/*
* 循环双链表的查找
* p = *L->next,循环体中用p做条件
* 这种写法便于对当前结点操作,查找、遍历使用这种形式
*/
Status GetElem(LoopDList L, int i, ElemType *e)
{
int j = 0; // 计数器
LoopDList p = L->next; // 指向第一个结点
while(p != L && j < i) // 判非空,判位置索引有效
{
p = p->next; // 指针后移
j++; // 计数器加1
}
if(p == L || j > i) // 判空,判位置索引无效
return ERROR;
*e = p->date; // 将p的数据域内容赋值给e
return OK;
}
6. 修改操作
/*
* 循环双链表的修改操作
*/
Status UpdateList(LoopDList *L, int i, ElemType e)
{
int j = 1; // 记录当前位置
LoopDList r = (*L)->next; // 指向第一个结点,此种写法便于岁当前结点操作
while(r != *L && j < i) // 判非空 ,判位置索引有效
{
r = r->next; // 指针后移
j++; // 计数器加1
}
if(r == *L || j > i) // 判空,判位置索引无效
return ERROR;
r->date = e; // 使r的数据域等于 e
return OK;
}
7.正序遍历
/*
* 循环双链表的正序遍历
*/
void PrintList1(LoopDList L)
{
LoopDList p = L->next; // 指向L第一个结点
if(p == L) // 判空
printf("表空
");
while(p != L) // 判非空
{
if(p->next != L)
printf("[%d] -> ", p->date);
else
printf("[%d]",p->date);
p = p->next;
}
printf("
");
}
8. 倒序遍历
/*
循环双链表的倒序遍历
*/
void PrintList2(LoopDList L)
{
LoopDList p = L->prior; // 指向L倒数第一个结点
if(p == L) // 判空
printf("表空
");
while(p != L) // 判非空
{
if(p->prior != L)
printf("[%d] -> ", p->date);
else
printf("[%d]",p->date);
p = p->prior;
}
printf("
");
}
9. 测试函数
int main()
{
LoopDList L = NULL; // 创建链表L
int i, e; // i为元素位置,e为元素内容
int n = 0;
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
n = sizeof(arr)/sizeof(arr[0]);
while(true)
{
printf("请选择对线性链表的操作:
");
printf("1.创建
");
printf("2.插入
");
printf("3.删除
");
printf("4.查找
");
printf("5.修改
");
printf("6.正序输出
");
printf("7.倒序输出
");
printf("8.退出
");
int a;
scanf("%d", &a);
switch(a)
{
case 1:
if(CreatList(L, arr, n))
printf("创建成功
");
else
printf("创建失败
");
break;
case 2:
printf("请输入需要插入的位置:");
scanf("%d", &i);
printf("请输入需要插入的元素:");
scanf("%d", &e);
if(LoopInsert(L, i, e))
printf("插入成功
");
else
printf("插入失败
");
break;
case 3:
printf("请输入需要删除的位置:");
scanf("%d", &i);
if(DelList(L, i, &e))
printf("删除成功
");
else
printf("删除失败
");
break;
case 4:
printf("请输入需要查找的位置:");
scanf("%d", &i);
GetElem(L, i, &e);
printf("第%d个元素为%d
",i,e);
break;
case 5:
printf("请输入需要修改的位置:");
scanf("%d", &i);
printf("请输入新的的元素:");
scanf("%d", &e);
if(UpdateList(&L, i, e))
printf("修改成功
");
else
printf("修改失败
");
break;
case 6:
if(L == NULL)
{
printf("表还未创建
");
break;
}
PrintList1(L);
break;
case 7:
if(L == NULL)
{
printf("表还未创建
");
break;
}
PrintList2(L);
break;
case 8:
return -1;
default:
printf("选择错误
");
break;
}
}
return 0;
}
参考
双链表实现1: https://blog.csdn.net/weixin_43810205/article/details/88626582
双链表实现2: https://www.cnblogs.com/likewithyou/p/5842984.html
图解链表: https://wk.baidu.com/view/b3cc07abb04e852458fb770bf78a6529647d35cc?pcf=2
循环单链表: https://www.cnblogs.com/yurui/p/9503164.html