需要实现一个消息队列,队列具有 FIFO 特点,即先入先出,在这里采用单向链表实现队列逻辑。

本次要实现的队列要求:

1. 节点可以存放任意类型数据

2. 线程安全

简单说明一下:

1. 创建CFNode类,用作节点,其data属性和next属性都是 atomic,即只能单线程访问属性。

2. 创建CFList类,用以push节点和pop节点

3. 删除操作为不必要操作,在这里实现了纯属个人技痒,同理可实现节点更新、插入等操作,在这里不做过多介绍。

CFList.h文件

  1. //
  2. // CFList.h
  3. // ListTest
  4. //
  5. // Created by MiaoCF on 2018/2/26.
  6. // Copyright © 2018年 MiaoCF. All rights reserved.
  7. //
  8.  
  9. #import <Foundation/Foundation.h>
  10.  
  11. typedef BOOL(^CFComparator)(id obj1, id obj2);
  12.  
  13. @interface CFNode : NSObject
  14.  
  15. @property (atomic, strong) id data;
  16. @property (atomic, strong) CFNode *next;
  17. @end
  18.  
  19. @interface CFList : NSObject
  20.  
  21. @property (atomic, strong, readonly) CFNode *head;
  22. @property (atomic, strong, readonly) CFNode *tail;
  23. @property (atomic, assign, readonly) NSInteger size;
  24.  
  25. // 1 creat
  26. - (instancetype)initList;
  27.  
  28. // 2 appendNode
  29. - (void)appendData:(id)data;
  30.  
  31. // 3 popNode
  32. - (id)popNode;
  33.  
  34. // 4 deleteNode
  35. - (BOOL)deletNode:(CFNode *)node with:(CFComparator)comparator;// func equal to find node
  36. @end

CFList.m文件

注意:

1. 使用了线程阻塞的互斥锁

2. 删除节点时,用户自己实现 CFComparator 进行比较。

3. 节点重复问题: 有多个节点数据相同 全部删除

  1. //
  2. // CFList.m
  3. // ListTest
  4. //
  5. // Created by MiaoCF on 2018/2/26.
  6. // Copyright © 2018年 MiaoCF. All rights reserved.
  7. //
  8.  
  9. #import "CFList.h"
  10.  
  11. @implementation CFNode
  12. @end
  13.  
  14. @interface CFList()
  15. @property (atomic, strong) NSLock *mutex;
  16. @end
  17.  
  18. @implementation CFList
  19.  
  20. - (instancetype)initList {
  21.  
  22. self = [super init];
  23.  
  24. _mutex = [[NSLock alloc] init];
  25.  
  26. self.head = nil;
  27. self.tail = nil;
  28.  
  29. return self;
  30. }
  31.  
  32. // idea: 记录 head 和 tail 节点, head只管删除节点, tail只管添加节点
  33.  
  34. - (void)appendData:(id)data {
  35. [_mutex lock];
  36.  
  37. CFNode *node = [[CFNode alloc] init];
  38. node.data = data;
  39. node.next = nil;
  40.  
  41. if (_head == nil) {
  42. _head = node;
  43. } else {
  44. _tail.next = node;
  45. }
  46. _tail = node;
  47. _size ++;
  48.  
  49. [_mutex unlock];
  50. }
  51.  
  52. - (id)popNode {
  53. [_mutex lock];
  54.  
  55. id res = nil;
  56.  
  57. if (_head != nil) {
  58. res = _head.data;
  59.  
  60. CFNode *temp = _head;
  61. _head = temp.next;
  62. if (_head == nil) {
  63. _tail = nil;
  64. }
  65.  
  66. temp.next = nil;
  67. _size --;
  68. }
  69.  
  70. [_mutex unlock];
  71. return res;
  72. }
  73.  
  74. // 节点重复问题: 有多个节点数据相同 如何处理?
  75.  
  76. - (BOOL)deletNode:(CFNode *)node with:(CFComparator)comparator{
  77.  
  78. [_mutex lock];
  79.  
  80. //空链表
  81. if (_head == nil) {
  82. [_mutex unlock];
  83. return NO;
  84. }
  85.  
  86. CFNode *currentNode = _head;
  87. CFNode *previousNode = currentNode;
  88.  
  89. //从第二个节点开始判断
  90. while (currentNode) {
  91.  
  92. if (comparator(currentNode, node)) { //移除节点
  93.  
  94. previousNode.next = currentNode.next;
  95. currentNode.next = nil;
  96.  
  97. // 节点重复问题: 有多个节点数据相同 全部删除
  98. if (previousNode.next == nil) { // 一直遍历到末尾,可以清除重复节点
  99.  
  100. [_mutex unlock];
  101. return YES;
  102. }
  103. }
  104. previousNode = currentNode;
  105. currentNode = currentNode.next;
  106.  
  107. }
  108.  
  109. [_mutex unlock];
  110. return NO;
  111. }
    113 @end

OC实现 单向链表的更多相关文章

  1. 复习下C 链表操作(单向链表)

    Object-C 作为C 的包装语言(运行时.消息机制).如果不熟悉C 的话实在玩得太肤浅. 随便深入oc 内部都会接触到C. runtime .GCD.Block.消息机制... 所有强大的功能无不 ...

  2. Reverse Linked List II 单向链表逆序(部分逆序)

    0 问题描述 原题点击这里. 将单向链表第m个位置到第n个位置倒序连接.例如, 原链表:1->2->3->4->5, m=2, n =4 新链表:1->4->3-& ...

  3. 【编程题目】输入一个单向链表,输出该链表中倒数第 k 个结点

    第 13 题(链表):题目:输入一个单向链表,输出该链表中倒数第 k 个结点.链表的倒数第 0 个结点为链表的尾指针.链表结点定义如下: struct ListNode {int m_nKey;Lis ...

  4. 输出单向链表中倒数第k个结点

    描述 输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第0个结点为链表的尾指针. 链表结点定义如下: struct ListNode { int       m_nKey; ListNode* ...

  5. Linus:利用二级指针删除单向链表

    Linus大神在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level codi ...

  6. 【转】Linus:利用二级指针删除单向链表

    原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多, ...

  7. C语言实现单向链表及其各种排序(含快排,选择,插入,冒泡)

    #include<stdio.h> #include<malloc.h> #define LEN sizeof(struct Student) struct Student / ...

  8. 数据结构——Java实现单向链表

    结点类: /** * @author zhengbinMac * 一个OnelinkNode类的对象只表示链表中的一个结点,通过成员变量next的自引用方式实现线性表中各数据元素的逻辑关系. */ p ...

  9. 输入一个单向链表,输出该链表中倒数第K个结点

    输入一个单向链表,输出该链表中倒数第K个结点,具体实现如下: #include <iostream> using namespace std; struct LinkNode { publ ...

随机推荐

  1. CSS之inline和inline-block

    inline-block 控制台-代码: PS:inline-block是让元素以内联形式存在,也就是不是块级,但是表现起来(又具有块级元素的高度)--也就是可以调高度(margin或者padding ...

  2. 终止ajax请求

    在做搜索功能时,文本框输入文本就得请求一次数据,如果上一次的请求还没回又请求了就导致数据错误和无用的数据请求. 我们需要输入文本时候判断上一次的ajax请求是否完毕,若还没完毕就终止本次请求. 对于j ...

  3. jquery解析XML在IE7下不兼容的问题

    jquery在解析XML内容的时候在IE7下无法显示,是因为数据格式的问题,解决办法如下: $.ajax({        type:"POST",        url:&quo ...

  4. JavaScript练习笔记整理·4 - 6.26

    基础练习(1): 我的解答为: function getMiddle(s) { if(s.length%2 == 0) { return s.charAt(s.length/2-1)+s.charAt ...

  5. arcMap 进度条

    private void kk() { IProgressDialogFactory progressDialogFactory = new ProgressDialogFactoryClass(); ...

  6. Android recyclerview删除item刷新列表

    删除item坑 mModels.remove(i); notifyItemRemoved(i); //必须调用这行代码 notifyItemRangeChanged(i, mModels.size() ...

  7. shell 脚本解压war包+备份+tomcat自动关闭+启动

    公司的开发环境每次替换war包时候,老是需要重新上传并且手动解压,然后再去重启tomcat.觉得这样子太麻烦了,于是写了一个shell脚本,自动解压+备份+tomcat自动关闭+启动.代码如下: #关 ...

  8. 并发包同步工具CyclicBarrier

    /** * * @描述: 同步工具 * 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指点地点集合碰合 . * @作者: Wnj . * @创建时间: 2017年5月16日 . * @版本: ...

  9. MySQL MHA搭建

    MHA算是业内比较成熟的MySQL高可用解决方案,在MySQL故障切换过程中,MHA能做到自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义 ...

  10. wget 模拟 get post请求

    wget命令 默认采用GET请求, 如果使用POST请求, wget --post-data '' url              // 这样 POST 请求没有请求体.