线性表 - 循环链表

来都来了 2020-10-19 13:43:09 ⋅ 890 阅读
1.引子
单链表解决了从A 查找到E的过程,假设现在要求从E 查找到A,用时最短,
因为单链表是单向的,只能从前往后,无法解决这个问题。因此引出了循环链表。
 
思路图
将单链表的终端结点的指针由空指针改为头结点,就使整个单链表形成一个环。
这种头尾相接的单链表成为单循环链表,简称循环链表

循环链表和单链表的主要差异就在于循环判断条件上,原来是判断p->next 是否为空,
现在则是p->next 不等于头结点。则循环未结束
2.循环链表的使用
#include <stdio.h>
#include <stdlib.h>


#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType;
typedef struct node {
    ElemType data;
    struct node *next;
} Node,*LinkList;


/** 初始化链表 next指向自身*/
void Init_circleList(LinkList *list) {
    (*list) = (LinkList)malloc(sizeof(Node));
    (*list)->next = *list;
}


/** 从1开始 创建n个数据 */
void create_circlrList(LinkList list, int n) {
    LinkList rear, s;
    rear = list;

    for (int i = 1; i <= n; i++) {
        s = (LinkList) malloc(sizeof(Node));
        s->data = I;
        rear->next = s;
        rear = s;
    }
    rear->next = list;
}


/** 获得链表的长度 */
int get_circle_list_Length(LinkList list) {
    LinkList headr = list->next;
    int count =0;
    while (headr != list) {
        headr = headr->next;
        count++;
    }
    return count;
}


/** 在某个位置插入某个元素*/
Status insert_circleList(LinkList list, int i, ElemType e) {
    
    if (i < 0 ) {
        return ERROR;
    }
    
    LinkList headr = list;
    LinkList node = (LinkList)malloc(sizeof(Node));
    node->data = e;
    
    //区分中间插入 or  尾部插入 or 头插
    if (i == 0) {
        node->next = headr->next;
        headr->next = node;
    } else if(i == get_circle_list_Length(list)+1) {
        
        while (headr->next != list) {
            headr = headr->next;
        }
        headr->next = node;
        node->next = list;
        
    } else {
        for (int k = 1; k < i; k++) {
            headr = headr->next;
        }
        node->next = headr->next;
        headr->next = node;
    }
    return OK;
}

/** 删除某一个元素 需要考虑头、尾、中间*/
Status delete_Node_circleList(LinkList list, int kill) {
    LinkList header = list;
    LinkList deleteNodel;
    
    int currentAllCount = get_circle_list_Length(list);
    
    if (kill > currentAllCount) {
        return ERROR;
    }
    if (kill == 0) {
        deleteNodel = header->next;
        header->next = deleteNodel->next;
        free(deleteNodel);
    } else if (kill == currentAllCount) {
        
        for (int i = 1; i < currentAllCount; i++) {
            header = header->next;
        }
        deleteNodel = header->next;
        header->next = deleteNodel->next;
        
        free(deleteNodel);
        
    } else {
        
        for (int i = 1; i < kill; i++) {
            header = header->next;
        }
        deleteNodel = header->next;
        header->next = deleteNodel->next;
        free(deleteNodel);
    }
    return OK;
}


/** 遍历链表*/
void Iteretor_circleList(LinkList list) {
    
    LinkList headr = list->next;
    while (headr != list) {
        printf("+++ current data is %d\n",headr->data);
        headr = headr->next;
    }
}


#pragma mark - 使用
void k_circleNodel(void) {
    LinkList list;
    Init_circleList(&list);
    create_circlrList(list, 10);
    Iteretor_circleList(list);
    
    printf("\n\n");
    insert_circleList(list, 4, 13);
    Iteretor_circleList(list);
    
    printf("\n\n");
    delete_Node_circleList(list, 10);
    Iteretor_circleList(list);
}

3.将两个单链表合并成一个循环链表
 
两个单链表
 
合并流程
整个过程需要借助一个指针作为临时变量,并祛除一个的头结点

1.p = rearA -> next;    //保存A的头结点
2.rearA->next = rearB->next-next;
//将本是指向B的第一个结点(不是头结点) 赋值给rearA->next
3.rearB->next = p; //将原A表的头结点赋值给rearB->next
4.free(p);
 
 


作者:挽弓如月_80dc
链接:https://www.jianshu.com/p/b398b9c6fd88
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

全部评论: 0

    我有话说:

    什么情况下才需要分库分

    我请教一下,我模拟测试,搞了几张大都是3千万左右的数据,带主键查询秒级响应,jmeter插入能够达到每秒6、700条左右,我业务量每秒就是300条左右插入,这个场景下是否不需要考虑分库分的问题?

    线性 - 栈与队列

    1.栈 1.栈(stack)是限定仅在尾进行插入和删除操作的线性,(先进后出) 2.我们把允许插入和删除的一端成为栈顶(top) 另一端称为栈底(bottom),不含任何数据元素的栈称为空栈

    为什么说作为程序员分库分的必要性一定要掌握?

      互联网大厂程序员必须掌握海量数据和高并发问题处理技能,期望进入大厂的程序员一定要仔细看这篇! MySQL 分库分是做什么的? 相信很多程序员对 MySQL 都比较熟悉了,目前国内

    「轻阅读」大众点评是如何分分库的?

    原大众点评的订单单早就已经突破两百G,由于查询维度较多,即使加了两个从库,优化索引,仍然存在很多查询不理想

    架构实战篇(五):Spring Boot 单验证和异常处理

    为了让API 能够更好的提供服务,单数据验证和异常的处理是必不可少的,让我们来看看怎么处理......

    Java Web实战篇:增强for循环实现原理及for循环实战性能优化

    Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator被创建之后会建立一个指向原来对象的单索引......

    MySql 8 新特性 - CTE 通用表达式(先睹为快)

    前言Mysql 8 正式发布了,新增了很多优秀特性,之后我会挑些重点来分享。下面和大家一起熟悉下 CTE......

    MySQL 插入 100万 条数据整理笔记

    多线程插入(单) 问:为何对同一个的插入多线程会比单线程快?同一时间对一个的写操作不应该是独占的吗? 答:在数据里做插入操作的时候,整体时间的分配是这样的: 1、多接耗时 (30

    使用 NodeJS 实现一个简单区块

    每天我们都会听说发现新的数字货币的消息,或者有人说它们是一个很快就会爆炸的大泡沫,其中只有区块会留下。

    分库分这样玩,可以永不迁移数据、避免热点

    中大型项目中,一旦遇到数据量比较大,小伙伴应该都知道就应该对数据进行拆分了。有垂直和水平两种。

    一文看懂mycat配置--数据库的读写分离、分分库

    波波说运维https://www.toutiao.com/i6742436467806568973 概述 系统开发中,数据库是非常重要的一个点。除了程序的本身的优化,如:SQL语句优化、代码优化,数据库的处理本身优化也是非常重要的。主从、热备、分...

    分库分工具:Apache ShardingSphere 5.0.0-alpha 发布

    Apache ShardingSphere 5.0.0 发布了 alpha 版本,自上个版本 4.1.1 发布以来,Apache ShardingSphere 一直在修复社区反馈的问题、加强功能和开发新特性。 根据官方的说法,5.x 是 Apac...

    JimuReport 积木报 1.3.3 版本发布,可视化报表工具

    项目介绍 积木报表,是一款免费的可视化Web报表工具,像搭建积木一样在线拖拽设计报表!功能涵盖,数据报表、打印设计、图表报表、大屏设计等! 秉承“简单、易用、专业”的产品理念,极大的降低报表开发难度、缩短开发周期、节省成本、解决各类报表难题,重...

    DataGear 2.1.0 发布,数据可视化分析平台

    DataGear 2.1.0 发布了,新增四种内置数据可视化图,具体更新内容如下: 新增:新增四种内置图表:径向柱状图、角度柱状图、堆叠径向柱状图、堆叠角度柱状图; 新增

    前端实战篇:通过JS抓取城市所有站点与线路

    做公交线路定位,木有数据怎么办?网上抓去~ 手把手教你通过JS实现站点线路数据抓取

    老板要我开发一个简单的工作流引擎

    第1关 一天,老板找到我,说要做个简单的工作流引擎。 我查了一天啥是工作流,然后做出了如下版本: 按顺序添加任意个审批人组成一个,最后加一个结束节点 记录当前审批人,当审批完后,审批人向后

    MySQL数据库开发需要注意的小细节整理

    尽量不在数据库做运算控制单数据量 纯INT不超过10M条,含Char不超过5M条保持身段苗条平衡范式和冗

    「转载」微服务分布式架构中,如何实现日志路跟踪?

    一个用户请求一个url,整个路如图,每个处理层...

    街电-共享充电宝行业独角兽/谁说“中国人愿意用隐私换便利”?/快播王欣微博看好区块/全民K歌闷声发大财

    街电-共享充电宝行业独角兽;谁说“中国人愿意用隐私换便利”?;快播王欣微博看好区块;全民K歌闷声发大财