数据结构只因双向循环链表

一个结构体包含两个指针:一个是前驱,另一个是后驱

看似复杂代码写起来是罕见单的,所以……

上代码熟悉!!!!源码放在下面了,很简单供复习所用

//结构体写出来
typedef struct List
{
      int data;
      struct List* prev;   //前后指针
      struct List* Next;
}ListNode;

不管你是顺序表还是单链表或者循环链表还是队列栈都要包含这些头文件

#include<stdio.h>
#include<stdlib.h>       //一般是free要用到
#include<assert.h>       //断言
#include<stdbool.h>      //bool

写一个简单的接口那一定是新建节点和初始化两者简单也最基础:

#include“List.h”  //函数接口在.c文件中要引用

//增加节点函数

SL*Add(int x)
{
   ListNode*newnode=(ListNode*)malloc(sizeof(SL)); //不多解释懂得都懂 
   newnode->prev=NULL;
   newnode->Next=NULL;
   newenode->data=x
   return newnode;
}

//初始化函数

SL* SqlInit()
{
    ListNode*phead=Add(0);
    phead->prev=phead; //为什么会指向自己呢?有什么好处?? 简单想一下是不是会形成闭环
    phead->Next=phead;
    return phead;
}

上面的代码虽然没有亮这个颜色,但并不代表他不对只不过有些东西没法引入

初始化为何要进行返回值呢??顺序表不用返回呀。这是为何呢??这是与主代码中的操作有关,在这里我就不写了,直接吧visual studio2022的代码拿过来了

上图是顺序表的图 他要把顺序表初始化才好增删查改

上图的表是循环链表的图,因为调用者需要知道链表的起始位置,以便后续操作(如添加、删除、遍历节点等

上面的只是小菜,循环链表的核心是增删查改。简单写一个尾插接口,并且简单分析一下。

//尾插
void ListPushBack(ListNode*phead,int x)
{
    assert(phead);   //断言防止phead为空指针,当然在上面已经初始化了不存在空
    ListNode*tail=phead->prev;
    ListNode*newnode=BuyListNode(x);
    newnode->Next=phead;
    newnode->prev=tail;
    tail->Next=newmode;
    phead->prev=newnode;

}

用图来解释可能更好

如果没有数据,尾插可不可以呢?答案是可以的因为在初始化中phead->Next = phead;
phead->prev= phead; 这段代码的精妙之处在尾插就凸显出来了。

尾插写完头插也是一样的思路我就直接上图了

其实可以用一种随机插入来替代尾插头插

//在随机插入之前需要找到位置所以要写一个查找函数
ListNode* ListFind(ListNode* phead, LTDateType x)
{
   assert(phead);
   ListNode* cur=phead->Next;
   while(cur!=phead)
{
   if(cur->data==x)
   {
      return cur;
   }
   cur=cur->Next;
}  
   return NULL;

}


//接下来就是随机插入接口了
ListNode* ListIsert(ListNode*pos,LTDateType x)
{
     assert(pos);
     ListNode* prev = pos->prev;
     ListNode* newnote = BuyListNode(x);  
     prev->Next = newnote;
     newnote->Next = pos;
     newnote->prev = prev;
     pos->prev = newnote;
}

销毁函数如下:

void ListDestory(ListNode* phead)
{
	ListNode* cur = phead->Next;
	while (cur != phead)
	{
		ListNode* Next = phead->Next;//继续销毁
		free(cur);
		cur = Next;
                
	}
	free(phead);
	phead = NULL;
}

以上就是基本的接口。看似简单实则比顺序表、单链表都简单。用两个指针解决了棘手问题。

那么在实际应用开发中双向循环链表用什么应用吗?不防让kimi来回答一下:

在让chatgpt来回答一下:

两者差不多少,其实不管是双向的还是单向的对数据的索引几乎没有差别。无非循环的是循环而已,在实际应用开发几乎没有差别。在一些细微方面有所区别:比如线程安全并发控制上。单链表在插入或删除头部节点时性能较好。其实差别微小到看不见。

### 小米手环9开发电脑端表盘 对于小米手环9的电脑端表盘开发,虽然官方并未公开详细的API文档供第三方开发者直接调用手环硬件资源,但从开源社区获取的经验来看,可以借鉴类似的项目来实现这一目标。Mi-Band作为一个开源项目,旨在为小米手环提供第三方支持扩展功能[^1]。 #### 环境搭建 要开始开发前,需先准备好开发环境: - 安装Python及其依赖库,用于解析蓝牙协议并与设备通信。 - 使用GitHub上的`mi-band`项目作为基础框架,此项目已经实现了与多个版本的小米手环之间的基本交互逻辑。 #### 数据传输机制理解 深入研究现有的源码可以帮助理解如何通过BLE(Bluetooth Low Energy)接口发送指令给手环并接收返回的数据包。这一步骤至关重要,因为所有的自定义设置都需要经过这条路径传递到穿戴设备上。 #### 设计表盘界面 针对电脑端显示的需求,设计适合大屏幕展示的手表面板样式。考虑到用户体验,应该注重图形化效果以及信息布局合理性。可利用HTML/CSS/JavaScript构建网页形式的应用程序,在浏览器窗口中模拟手表外观,并借助WebSocket或其他网络技术实现实时数据交换。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Custom Mi Band Watchface</title> <!-- 引入必要的CSS文件 --> <link rel="stylesheet" href="./styles.css"/> </head> <body> <div id="watch-face"></div> <script src="./app.js"></script> </body> </html> ``` ```css /* styles.css */ #watch-face { width: 300px; height: 300px; background-color: black; color: white; display: flex; justify-content: center; align-items: center; } ``` ```javascript // app.js document.getElementById(&#39;watch-face&#39;).innerHTML = ` <h1>${new Date().toLocaleTimeString()}</h1>`; setInterval(() => { document.querySelector(&#39;#watch-face h1&#39;).textContent = new Date().toLocaleTimeString(); }, 1000); ``` 上述代码片段展示了创建一个简单的静态时间显示器的方法。实际应用中还需要考虑更多因素如日期、天气预报等功能模块集成。 #### 实现双向通讯 最后也是最重要的一点就是建立稳定的PC至手环间的连接通道。由于不同型号之间可能存在差异,建议参考具体产品的技术手册或者向更广泛的开发者群体寻求帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值