直接贴出完整代码,每个函数的功能及部分代码的解释都在注释中,代码亲测可行

/*
2018.8.15
注意三点:
1.不要将循环写成if    //很尴尬,主要是我犯了这个错误,找了半天还没找出来,第二天看的时候才发现,非常的尴尬
2.循环链表的判空操作是 p->rear != *L
3.p = *L,循环体中用p->rear做条件 这种写法便于对当前结点的前一结点操作,插入、删除、修改操作使用这种形式
p = *L->rear,循环体中用p做条件 这种写法便于对当前结点操作,查找、遍历使用这种形式
       4.双向链表在插入与删除时,要处理好前驱指针和后继指针,切不可遗忘。尤其是插入时,要将新点之后的结点的前驱指向新结点,这里容易被忽略
*/ #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 *pront; //指向前一结点的指针
ElemType date; //结点元素
struct Node *rear; //指向后一结点的指针
}Node; typedef struct Node *LoopList; //创建链表 /*
循环双向链表的插入操作
*/
Status LoopInsert(LoopList *L, int i, ElemType e)
{
int j = ; //计数器,记录当前位置
LoopList r = *L; //指向L //此种写法便于对当前结点的上一结点进行操作
LoopList s; //用于创建新结点
// while(r->rear && j < i) //判非空 判位置索引合理 //循环链表的判断非空不是这样的 2018.8.15
while(r->rear != *L && j < i)
{
r = r->rear; //指针后移
j++; //计数器加1
}
if(r->rear == *L || j > i) //判空 判位置索引不合理
return ERROR;
s = (LoopList)malloc(sizeof(Node)); //开辟新结点s
s->date = e; //为s的数据域赋值
r->rear->pront = s; //使插入结点后的下一结点的前驱指向s
s->rear = r->rear; //使s的后继结点等于r的后继结点
s->pront = r; //使s的前驱结点等于r
r->rear = s; //使r得后继结点等于s
return OK;
} /*
循环双向链表的删除操作
*/
Status DelList(LoopList *L, int i, ElemType *e)
{
int j = ; //记录当前位置
LoopList r = *L; //指向链表
LoopList s; //用于释放要删除的结点
while(r->rear != *L && j < i) //判非空 判索引位置有效
{
r = r->rear; //指针后移
j++; //计数器加1
}
if(r->rear == *L || j > i) //判空 判索引位置无效
return ERROR;
s = r->rear; //使s指向r
*e = s->date; //将要删除的结点数据赋值给e
r->rear = s->rear; //使r的后继结点等于r的后继结点
s->rear->pront = r; //使s的后继的前驱结点等于r
free(s); //释放s结点
return OK;
} /*
循环双链表的修改操作
*/
Status UpdateList(LoopList *L, int i, ElemType e)
{
int j = ; //记录当前位置
LoopList r = (*L)->rear; //指向第一个结点 //此种写法便于岁当前结点操作
while(r != *L && j < i) //判非空 判位置索引有效
{
r = r->rear; //指针后移
j++; //计数器加1
}
if(r == *L || j > i) //判空 判位置索引无效
return ERROR;
r->date = e; //使r的数据域等于 e
return OK;
} /*
循环双链表的查找
*/
Status GetElem(LoopList L, int i, ElemType *e)
{
int j = ; //计数器
LoopList r = L->rear; //指向第一个结点
while(r != L && j < i) //判非空 判位置索引有效
{
r = r->rear; //指针后移
j++; //计数器加1
}
if(r == L || j > i) //判空 判位置索引无效
return ERROR;
*e = r->date; //将r的数据域内容赋值给e
return OK;
} /*
循环双链表的正序遍历
*/
void PrintList1(LoopList L)
{
int j = ;
LoopList r = L->rear; //指向L第一个结点
if(r == L) //判空
printf("表空\n");
while(r != L) //判非空
{
printf("第%d个结点的数据是%d\n",j,r->date);
r = r->rear;
j++;
}
printf("\n");
} /*
循环双链表的倒序遍历
*/
void PrintList2(LoopList L)
{
int j = ;
LoopList r = L->pront; //指向L倒数第一个结点
if(r == L) //判空
printf("表空\n");
while(r != L) //判非空
{
printf("倒数第%d个结点的数据是%d\n",j,r->date);
r = r->pront;
j++;
}
printf("\n");
} /*
循环双链表的创建
*/
Status CreatList(LoopList *L, int n)
{
int i; //计数器
(*L) = (LoopList)malloc(sizeof(Node)); //创建头结点
LoopList s,q; //s用于开辟新结点,q指向表尾
srand(time()); //初始化随机数种子
q = *L; //指向表尾结点
for(i = ; i < n; i++)
{
s = (LoopList)malloc(sizeof(Node)); //开辟新结点
s->date = rand() % + ; //为新结点赋值
q->rear = s; //让表尾结点的后继结点指向新结点
s->pront = q; //让新结点的前驱结点指向q
q = s; //表尾结点指针后移
}
q->rear = *L; //使表尾结点的后继指针指向头结点
(*L)->pront = q; //头指针的前驱结点指向表尾结点
return OK;
} void main()
{
LoopList L = NULL; //创建链表L
int i, e; //i为元素位置,e为元素内容 while(true)
{
printf("请选择对线性链表的操作:\n");
printf("1.创建\n");
printf("2.插入\n");
printf("3.删除\n");
printf("4.查找\n");
printf("5.修改\n");
printf("6.正序输出\n");
printf("7.倒序输出\n");
printf("8.退出\n");
int a;
scanf("%d", &a);
switch(a)
{
case :
printf("请输入需要创建元素的个数:");
scanf("%d", &i);
if(CreatList(&L, i))
printf("创建成功\n");
else
printf("创建失败\n");
break;
case :
printf("请输入需要插入的位置:");
scanf("%d", &i);
printf("请输入需要插入的元素:");
scanf("%d", &e);
if(LoopInsert(&L, i, e))
printf("插入成功\n");
else
printf("插入失败\n");
break;
case :
printf("请输入需要删除的位置:");
scanf("%d", &i);
if(DelList(&L, i, &e))
printf("删除成功\n");
else
printf("删除失败\n");
break;
case :
printf("请输入需要查找的位置:");
scanf("%d", &i);
GetElem(L, i, &e);
printf("第%d个元素为%d\n",i,e);
break;
case :
printf("请输入需要修改的位置:");
scanf("%d", &i);
printf("请输入新的的元素:");
scanf("%d", &e);
if(UpdateList(&L, i, e))
printf("修改成功\n");
else
printf("修改失败\n");
break;
case :
if(L == NULL)
{
printf("表还未创建\n");
break;
}
PrintList1(L);
break;
case :
if(L == NULL)
{
printf("表还未创建\n");
break;
}
PrintList2(L);
break;
case :
return;
default:
printf("选择错误\n");
break;
}
}
}

循环双向链表-C语言实现的更多相关文章

  1. 纯C语言实现循环双向链表创建,插入和删除

    #include <stdio.h> #include <stdlib.h> typedef int ElemType; typedef struct DLNode{ Elem ...

  2. (续)线性表之双向链表(C语言实现)

    在前文实现单向链表的基本操作下,本文实现双向链表的基本操作. 双向链表与单链表差异,是双向链表结点中有前向指针和后向指针.所以在插入和删除新结点元素时候不见要考虑后向指针还要考虑前向指针. 以下是双向 ...

  3. 字符串循环右移-c语言

    一个长度为len的字符串,对其循环右移n位 [期望]char str[] = "abcdefg";右移3次后,变成"efgabcd" [思路] 思路1. 如果用 ...

  4. 数据结构 双向链表 C语言实现

    dlist.h #ifndef __dList_H #define __dlist_H typedef int Item; typedef struct Node *PNode; typedef PN ...

  5. 定长循环队列C语言实现

    #ifndef _CONST_H_#define _CONST_H_ #include <stdio.h>#include <stdlib.h> typedef enum { ...

  6. 【数据结构】循环队列 C语言实现

    "Queue.h" #include "Queue.h" #include <stdio.h> #include <stdlib.h> ...

  7. 在django中使用循环与条件语言

    {% if not Article_type_id %} <li class="active"><a href="/">全部</a ...

  8. for循环(C语言型)举例

  9. for循环(C语言型)流程

随机推荐

  1. 学习笔记52_mongodb增删改查

    使用use db1作为当前数据库 如果没有db1,会自动创建 使用switch db2,当前数据库切换为db2 使用show dbs,显示当前所有数据库 使用show collection ,显示当前 ...

  2. [考试反思]1031csp-s模拟测试96:常态

    按照smily的说法这一场的大众分暴力分是不是265啊QwQ那我可真是个大垃圾 总算还是回归了常态. T3文件名写错,把“city.in”写成“city,in” 还好,只丢了20分. T2乱打$O(n ...

  3. [考试反思]0904NOIP模拟测试37:守望

    100分并列的还有4个没粘 总分是大脸的一半,然而还只低了2名.差距好大...但其实后面的分数段又很密集,和我都差不了多少... 我可能也是最水的那一个,排行榜前7个里面就我没有AC.全是暴力... ...

  4. noip模拟9 达哥随单题

    T1.随 看题第一眼,就瞄到最下面 孙金宁教你学数学  ?????原根?目测神题,果断跳过. 最后打了个快速幂,愉快的收到了达哥送来的10分. 实际上这题暴力不难想,看到一个非常小的mod应该就能想到 ...

  5. 【ASP.NET Core学习】Entity Framework Core

    这里介绍在ASP.NET Core中使用EF Core,这里数据库选的是Sql Server 如何使用Sql Server 添加模型 && 数据库迁移 查询数据 保存数据 如何使用Sq ...

  6. vue实现tab选项卡切换效果

    tab选项卡切换效果: 通过点击事件传入参数,然后通过v-show来进行切换显示 <template> <div class="box"> <div ...

  7. 安利一个绘制指引线的JS库leader-line

    前言 之前看到一篇推荐Magi这个搜索引擎的新闻,对于这个搜索引擎是否好用咱们不予置评,但是我在这个搜索引擎上面发现了一个好玩的前端功能. 如上图,将鼠标浮动到学习来源上时,会展示一堆指引线. 本博客 ...

  8. node.js 需要注意知识点

    复习node.js 需要注意知识点--(重点) 2.1:参数传递获取造型 客户端脚手架(发)    (参数传递)    node.js(收) -发ajax  this.axios.get(" ...

  9. Pandas进阶笔记 (一) Groupby 重难点总结

    如果Pandas只是能把一些数据变成 dataframe 这样优美的格式,那么Pandas绝不会成为叱咤风云的数据分析中心组件.因为在数据分析过程中,描述数据是通过一些列的统计指标实现的,分析结果也需 ...

  10. 装上linux后的准备工作

    A.修改对应网卡的IP地址的配置文件  1 2 3 4 5 6 7 8 # vi /etc/sysconfig/network-scripts/ifcfg-eth0   IPV6INIT=no #关闭 ...