PeopleCode实现LinkedList

链表集合类简介及对比Array:

    基于链表实现的列表集合
    在执行向头部插入(unshift)或删除(removeFirst)和两个集合合并(addLinkedList)或插入(setLinkedList)时速度远远高于Array
    在执行截取(interceptList)时速度远高于Array
    在执行随机插入(set)和替换(replace)时整体速度高于Array
    在执行末尾部插入或删除时理论速度与Array基本相同,但在peopleCode中速度会低于Array
    执行倒序(Reverse)时速度稍低于Array
    随机取数和使用for遍历时速度远低于Array,遍历时应使用迭代遍历或指针遍历方式

具体区别可参阅Java的ArrayList和LinkedList区别的相关文献。

链表集合节点使用any数组,数组第一位为上一个节点,第二位为本节点,第三位为下一节点

本来节点使用实体类实现,但是发现peopleCode对自定义class操作没有对any数组操作快。

peopleCode实现代码如下:

/* CSQ ADD 链表集合类 
	基于链表实现的列表集合
	在执行向头部插入(unshift)或删除(removeFirst)和两个集合合并(addLinkedList)或插入(setLinkedList)时速度远远高于Array
	在执行截取(interceptList)时速度远高于Array
	在执行随机插入(set)和替换(replace)时整体速度高于Array
	在执行末尾部插入或删除时速度与Array基本相同,但在peopleCode中速度会低于Array
	执行倒序(Reverse)时速度稍低于Array
	随机取数和使用for遍历时速度远低于Array,遍历时应使用迭代遍历或指针遍历方式
*/
/*
	链表集合节点使用any数组,数组第一位为上一个节点,第二位为本节点,第三位为下一节点。
	本来节点使用实体类实现,但是发现peopleCode对自定义class操作没有对any数组操作快。
*/

class LinkedList
   /* 集合长度 */
   property integer len get;
   /* 添加元素到集合末尾 */
   method add(&element As any);
   /* 添加节点到集合末尾。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method addNode(&node As array);
   /* 添加集合到集合末尾。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method addLinkedList(&linkedList As GT_COMMON:UTIL:LinkedList);
   
   /* 添加元素到集合前面 */
   method unshift(&element As any);
   /* 添加节点到集合前面。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method unshiftNode(&node As array);
   /* 添加集合到集合前面。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method unshiftLinkedList(&linkedList As GT_COMMON:UTIL:LinkedList);
   
   /* 插入元素到集合&index位置 */
   method set(&index As integer, &element As any);
   /* 插入节点到集合&index位置。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method setNode(&index As integer, &node As array);
   /* 插入集合到集合&index位置。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method setLinkedList(&index As integer, &linkedList As GT_COMMON:UTIL:LinkedList);
   
   /* 获取集合内第&index个元素 */
   method get(&index As integer) Returns any;
   /* 获取集合内第&index个节点 */
   method getNode(&index As integer) Returns array;
   /* 获取集合内第一个元素 */
   method getFirst() Returns any;
   /* 获取集合内第一个节点 */
   method getFirstNode() Returns array;
   /* 获取集合内最后一个元素 */
   method getLast() Returns any;
   /* 获取集合内最后一个节点 */
   method getLastNode() Returns array;
   
   /* 替换&startIndex到&endIndex元素为&element */
   method replace(&startIndex As integer, &endIndex As integer, &element As any);
   /* 替换&startIndex到&endIndex节点为&element。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method replaceNode(&startIndex As integer, &endIndex As integer, &node As array);
   /* 替换&startIndex到&endIndex节点为&linkedList。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method replaceToLinkedList(&startIndex As integer, &endIndex As integer, &linkedList As GT_COMMON:UTIL:LinkedList);
   /* 截取列表,保留从&startIndex到&endIndex的元素 */
   method interceptList(&startIndex As integer, &endIndex As integer);
   
   /* 倒序当前列表集合 */
   method reverse();
   
   /* 交换&index1和&index2的位置 */
   method exchange(&index1 As integer, &index2 As integer);
   
   /* 移除稽核内第&index个元素 */
   method remove(&index As integer);
   /* 移除稽核内第一个元素 */
   method removeFirst();
   /* 移除稽核内最后一个元素 */
   method removeLast();
   
   /* 返回集合长度 */
   method getSize() Returns integer;
   
   
   /* 以下为指针遍历LinkedList相关方法。
		正序遍历示例:
		&linkedList.initializePointerToFirst();
		while &linkedList.hasNext()
			&anyValue = &linkedList.next();	 
		end-while;
		倒序遍历示例:
		&linkedList.initializePointerToLast();
		while &linkedList.hasPrevious()
			&anyValue = &linkedList.previous();	 
		end-while;
   */
   method initializePointerToFirst();
   method initializePointerToLast();
   /* 初始化指针到指定的&index位置上 */
   method initializePointerToIndex(&index As integer);
   
   method hasNext() Returns boolean;
   method next() Returns any;
   method hasPrevious() Returns boolean;
   method previous() Returns any;
   
private
   instance integer &size;
   instance array &pointer;
   instance array &firstNode;
   instance array &lastNode;
end-class;

get len
   /+ Returns Integer +/
   Return %This.size;
end-get;

method add
   /+ &element as Any +/
   Local array &node = CreateArrayAny( Null, Null, Null);
   &node [2] = &element;
   %This.addNode(&node);
end-method;

method addNode
   /+ &node as Array of Any +/
   If %This.firstNode = Null Then
      %This.firstNode = &node;
      %This.lastNode = &node;
   Else
      %This.lastNode [3] = &node;
      &node [1] = %This.lastNode;
      %This.lastNode = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method addLinkedList
   /+ &linkedList as GT_COMMON:UTIL:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   Else
      If %This.size = 0 Then
         %This.firstNode = &linkedList.getFirstNode();
         %This.lastNode = &linkedList.getLastNode();
         %This.size = &linkedList.len;
         Return;
      End-If;
   End-If;
   Local array &node = &linkedList.getFirstNode();
   %This.lastNode [3] = &node;
   &node [1] = %This.lastNode;
   %This.lastNode = &linkedList.getLastNode();
   %This.size = %This.size + &linkedList.len;
end-method;

method unshift
   /+ &element as Any +/
   Local array &node = CreateArrayAny( Null, Null, Null);
   &node [2] = &element;
   %This.unshiftNode(&node);
end-method;

method unshiftNode
   /+ &node as Array of Any +/
   If %This.firstNode = Null Then
      %This.firstNode = &node;
      %This.lastNode = &node;
   Else
      %This.firstNode [1] = &node;
      &node [1] = Null;
      &node [3] = %This.firstNode;
      %This.firstNode = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method unshiftLinkedList
   /+ &linkedList as GT_COMMON:UTIL:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   Else
      If %This.size = 0 Then
         %This.firstNode = &linkedList.getFirstNode();
         %This.lastNode = &linkedList.getLastNode();
         %This.size = &linkedList.len;
         Return;
      End-If;
   End-If;
   Local array &node = &linkedList.getLastNode();
   %This.firstNode [1] = &node;
   &node [3] = %This.firstNode;
   %This.firstNode = &linkedList.getFirstNode();
   %This.size = %This.size + &linkedList.len;
end-method;

method set
   /+ &index as Integer, +/
   /+ &element as Any +/
   Local array &node = CreateArrayAny( Null, Null, Null);
   &node [2] = &element;
   %This.setNode(&index, &node);
end-method;

method setNode
   /+ &index as Integer, +/
   /+ &node as Array of Any +/
   If &index = 1 Then
      %This.firstNode [1] = &node;
      &node [1] = Null;
      &node [3] = %This.firstNode;
      %This.firstNode = &node;
   Else
      Local array &node2 = %This.getNode(&index);
      Local array &node1 = &node2 [1];
      &node [1] = &node1;
      &node1 [3] = &node;
      &node [3] = &node2;
      &node2 [1] = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method setLinkedList
   /+ &index as Integer, +/
   /+ &linkedList as GT_COMMON:UTIL:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   End-If;
   If &index = 1 Then
      Local array &node = &linkedList.getLastNode();
      %This.firstNode [1] = &node;
      &node [3] = %This.firstNode;
      %This.firstNode = &linkedList.getFirstNode();
   Else
      Local array &node2 = %This.getNode(&index);
      Local array &node1 = &node2 [1];
      Local array &nodeSet1 = &linkedList.getFirstNode();
      Local array &nodeSet2 = &linkedList.getLastNode();
      &nodeSet1 [1] = &node1;
      &node1 [3] = &nodeSet1;
      &nodeSet2 [3] = &node2;
      &node2 [1] = &nodeSet2;
   End-If;
   %This.size = %This.size + &linkedList.len;
end-method;

method get
   /+ &index as Integer +/
   /+ Returns Any +/
   Return %This.getNode(&index)[2];
end-method;

method getNode
   /+ &index as Integer +/
   /+ Returns Array of Any +/
   If &index > %This.size Then
      throw CreateException(0, 0, "数组越界:&index-" | &index | "不在集合1到" | %This.size | "范围内");
   End-If;
   Local array &node;
   Local integer &i;
   If (%This.size - &index) < &index Then /* &index靠后,从末尾开始查找 */
      &node = %This.lastNode;
      For &i = %This.size To 1 Step - 1
         If &index = &i Then
            Return &node;
         End-If;
         &node = &node [1];
      End-For;
   Else /* &index靠前,从头部开始查找 */
      &node = %This.firstNode;
      For &i = 1 To %This.size
         If &index = &i Then
            Return &node;
         End-If;
         &node = &node [3];
      End-For;
   End-If;
end-method;

method getFirst
   /+ Returns Any +/
   Return %This.firstNode [2];
end-method;

method getFirstNode
   /+ Returns Array of Any +/
   Return %This.firstNode;
end-method;

method getLast
   /+ Returns Any +/
   Return %This.lastNode [2];
end-method;

method getLastNode
   /+ Returns Array of Any +/
   Return %This.lastNode;
end-method;

method replace
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &element as Any +/
   Local array &node = CreateArrayAny( Null, Null, Null);
   &node [2] = &element;
   %This.replaceNode(&startIndex, &endIndex, &node);
end-method;

method replaceNode
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &node as Array of Any +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local array &node2 = %This.get(&endIndex)[3];
   Local array &node1 = %This.get(&startIndex)[1];
   If &node2 = Null Then
      %This.lastNode = &node;
   Else
      &node2 [1] = &node;
   End-If;
   &node [3] = &node2;
   &node [1] = &node1;
   If &node1 = Null Then
      %This.firstNode = &node;
   Else
      &node1 [3] = &node;
   End-If;
   %This.size = %This.size + &endIndex - &startIndex + 2;
end-method;

method replaceToLinkedList
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &linkedList as GT_COMMON:UTIL:LinkedList +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local array &node2 = %This.get(&endIndex)[3];
   Local array &node1 = %This.get(&startIndex)[1];
   Local array &nodeR2 = &linkedList.getLastNode();
   Local array &nodeR1 = &linkedList.getFirstNode();
   If &node2 = Null Then
      %This.lastNode = &nodeR2;
   Else
      &node2 [1] = &nodeR2;
   End-If;
   &nodeR2 [3] = &node2;
   &nodeR1 [1] = &node1;
   If &node1 = Null Then
      %This.firstNode = &nodeR1;
   Else
      &node1 [3] = &nodeR1;
   End-If;
   %This.size = %This.size + &endIndex - &startIndex + 1 + &linkedList.len;
end-method;

method interceptList
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local array &node1 = %This.get(&startIndex);
   Local array &node2 = %This.get(&endIndex);
   %This.firstNode = &node1;
   %This.lastNode = &node2;
   %This.firstNode [1] = Null;
   %This.lastNode [3] = Null;
   %This.size = &endIndex - &startIndex + 1;
end-method;

method reverse
   /* Local array &node1 = %This.firstNode;
   %This.firstNode = %This.lastNode;
   %This.lastNode = &node1;
   Local integer &i;
   Local array &node2 = &node1[3];
   Local array &node3;
   For &i = 1 To %This.size
      If &node2 = Null Then
         Break;
      End-If;
      &node3 = &node2[3];
      &node2[3] = &node1;
      &node1[1] = &node2;
      &node1 = &node2;
      &node2 = &node3;
   End-For;
   %This.firstNode[1] = Null;
   %This.lastNode[3] = Null; */
   Local array &nodeLeft = %This.firstNode;
   Local array &nodeRight = %This.lastNode;
   Local integer &i = 1;
   Local any &any;
   While True
      If &i * 2 > %This.size Then
         Return;
      End-If;
      &any = &nodeLeft [2];
      &nodeLeft [2] = &nodeRight [2];
      &nodeRight [2] = &any;
      &nodeLeft = &nodeLeft [3];
      &nodeRight = &nodeRight [1];
      &i = &i + 1;
   End-While;
end-method;

method exchange
   /+ &index1 as Integer, +/
   /+ &index2 as Integer +/
   Local array &node1 = %This.get(&index1);
   Local array &node2 = %This.get(&index2);
   Local any &any = &node1 [2];
   &node1 [2] = &node2 [2];
   &node2 [2] = &any;
end-method;

method remove
   /+ &index as Integer +/
   If &index = 1 Then
      %This.removeFirst();
      Return;
   Else
      If &index = %This.size Then
         %This.removeLast();
         Return;
      End-If;
   End-If;
   Local array &node = %This.get(&index);
   &node [1][3] = &node [3];
   &node [3][1] = &node [1];
   %This.size = %This.size - 1;
end-method;

method removeFirst
   If %This.size < 2 Then
      %This.firstNode = Null;
      %This.lastNode = Null;
      %This.size = 0;
   Else
      %This.firstNode = %This.firstNode [3];
      %This.firstNode [1] = Null;
      %This.size = %This.size - 1;
   End-If;
end-method;

method removeLast
   If %This.size < 2 Then
      %This.firstNode = Null;
      %This.lastNode = Null;
      %This.size = 0;
   Else
      %This.lastNode = %This.lastNode [1];
      %This.lastNode [3] = Null;
      %This.size = %This.size - 1;
   End-If;
end-method;

method getSize
   /+ Returns Integer +/
   Return %This.size;
end-method;

method initializePointerToFirst
   %This.pointer = %This.firstNode;
end-method;

method initializePointerToLast
   %This.pointer = %This.lastNode;
end-method;

method initializePointerToIndex
   /+ &index as Integer +/
   %This.pointer = %This.getNode(&index);
end-method;

method hasNext
   /+ Returns Boolean +/
   Return (%This.pointer <> Null);
end-method;

method next
   /+ Returns Any +/
   Local array &nd = %This.pointer;
   %This.pointer = %This.pointer [3];
   Return &nd [2];
end-method;

method hasPrevious
   /+ Returns Boolean +/
   Return (%This.pointer <> Null);
end-method;

method previous
   /+ Returns Any +/
   Local array &nd = %This.pointer;
   %This.pointer = %This.pointer [1];
   Return &nd [2];
end-method;

以下是向第一位插入2万个元素测试,对比Array:

向最后一位插入2万个元素对比:

以下是旧实现代码,节点使用实体类实现,更便于理解。仅用于示例,代码不再更新。

LinkedList类:

/* CSQ ADD 链表集合类 
	基于链表实现的列表集合
	在执行向头部插入(unshift)或删除(removeFirst)和两个集合合并(addLinkedList)或插入(setLinkedList)时速度远远高于Array
	在执行截取(interceptList)时速度远高于Array
	在执行随机插入(set)和替换(replace)时整体速度高于Array
	在执行末尾部插入或删除时速度与Array基本相同
	执行倒序(Reverse)时速度稍低于Array
	随机取数和使用for遍历时速度远低于Array,遍历时应使用迭代遍历或指针遍历方式
*/
import COMMON:util:entity:LinkedNode;

class LinkedList
   /* 集合长度 */
   property integer len get;
   /* 添加元素到集合末尾 */
   method add(&element As any);
   /* 添加节点到集合末尾。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method addNode(&node As COMMON:util:entity:LinkedNode);
   /* 添加集合到集合末尾。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method addLinkedList(&linkedList As COMMON:util:LinkedList);
   
   /* 添加元素到集合前面 */
   method unshift(&element As any);
   /* 添加节点到集合前面。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method unshiftNode(&node As COMMON:util:entity:LinkedNode);
   /* 添加集合到集合前面。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method unshiftLinkedList(&linkedList As COMMON:util:LinkedList);
   
   /* 插入元素到集合&index位置 */
   method set(&index As integer, &element As any);
   /* 插入节点到集合&index位置。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method setNode(&index As integer, &node As COMMON:util:entity:LinkedNode);
   /* 插入集合到集合&index位置。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method setLinkedList(&index As integer, &linkedList As COMMON:util:LinkedList);
   
   /* 获取集合内第&index个元素 */
   method get(&index As integer) Returns any;
   /* 获取集合内第&index个节点 */
   method getNode(&index As integer) Returns COMMON:util:entity:LinkedNode;
   /* 获取集合内第一个元素 */
   method getFirst() Returns any;
   /* 获取集合内第一个节点 */
   method getFirstNode() Returns COMMON:util:entity:LinkedNode;
   /* 获取集合内最后一个元素 */
   method getLast() Returns any;
   /* 获取集合内最后一个节点 */
   method getLastNode() Returns COMMON:util:entity:LinkedNode;
   
   /* 替换&startIndex到&endIndex元素为&element */
   method replace(&startIndex As integer, &endIndex As integer, &element As any);
   /* 替换&startIndex到&endIndex节点为&element。注意:此方法会改变&node的前后指针,导致原本引用此节点的LinkedList实例的结构失效! */
   method replaceNode(&startIndex As integer, &endIndex As integer, &node As COMMON:util:entity:LinkedNode);
   /* 替换&startIndex到&endIndex节点为&linkedList。注意:此方法会改变&linkedList的指针数据,导致传入的&linkedList不可用! */
   method replaceToLinkedList(&startIndex As integer, &endIndex As integer, &linkedList As COMMON:util:LinkedList);
   /* 截取列表,保留从&startIndex到&endIndex的元素 */
   method interceptList(&startIndex As integer, &endIndex As integer);
   
   /* 倒序当前列表集合 */
   method reverse();
   
   /* 交换&index1和&index2的位置 */
   method exchange(&index1 As integer, &index2 As integer);
   
   /* 移除稽核内第&index个元素 */
   method remove(&index As integer);
   /* 移除稽核内第一个元素 */
   method removeFirst();
   /* 移除稽核内最后一个元素 */
   method removeLast();
   
   /* 返回集合长度 */
   method getSize() Returns integer;
   
   
   /* 以下为指针遍历LinkedList相关方法。
		正序遍历示例:
		&linkedList.initializePointerToFirst();
		while &linkedList.hasNext()
			&anyValue = &linkedList.next();	 
		end-while;
		倒序遍历示例:
		&linkedList.initializePointerToLast();
		while &linkedList.hasPrevious()
			&anyValue = &linkedList.previous();	 
		end-while;
   */
   method initializePointerToFirst();
   method initializePointerToLast();
   /* 初始化指针到指定的&index位置上 */
   method initializePointerToIndex(&index As integer);
   
   method hasNext() Returns boolean;
   method next() Returns any;
   method hasPrevious() Returns boolean;
   method previous() Returns any;
   
private
   instance integer &size;
   instance COMMON:util:entity:LinkedNode &pointer;
   instance COMMON:util:entity:LinkedNode &firstNode;
   instance COMMON:util:entity:LinkedNode &lastNode;
end-class;

get len
   /+ Returns Integer +/
   Return %This.size;
end-get;

method add
   /+ &element as Any +/
   Local COMMON:util:entity:LinkedNode &node = create COMMON:util:entity:LinkedNode(&element);
   %This.addNode(&node);
end-method;

method addNode
   /+ &node as COMMON:util:entity:LinkedNode +/
   If %This.firstNode = Null Then
      %This.firstNode = &node;
      %This.lastNode = &node;
   Else
      %This.lastNode.nextNode = &node;
      &node.previousNode = %This.lastNode;
      %This.lastNode = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method addLinkedList
   /+ &linkedList as COMMON:util:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   Else
      If %This.size = 0 Then
         %This.firstNode = &linkedList.getFirstNode();
         %This.lastNode = &linkedList.getLastNode();
         %This.size = &linkedList.len;
         Return;
      End-If;
   End-If;
   Local COMMON:util:entity:LinkedNode &node = &linkedList.getFirstNode();
   %This.lastNode.nextNode = &node;
   &node.previousNode = %This.lastNode;
   %This.lastNode = &linkedList.getLastNode();
   %This.size = %This.size + &linkedList.len;
end-method;

method unshift
   /+ &element as Any +/
   Local COMMON:util:entity:LinkedNode &node = create COMMON:util:entity:LinkedNode(&element);
   %This.unshiftNode(&node);
end-method;

method unshiftNode
   /+ &node as COMMON:util:entity:LinkedNode +/
   If %This.firstNode = Null Then
      %This.firstNode = &node;
      %This.lastNode = &node;
   Else
      %This.firstNode.previousNode = &node;
      &node.previousNode = Null;
      &node.nextNode = %This.firstNode;
      %This.firstNode = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method unshiftLinkedList
   /+ &linkedList as COMMON:util:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   Else
      If %This.size = 0 Then
         %This.firstNode = &linkedList.getFirstNode();
         %This.lastNode = &linkedList.getLastNode();
         %This.size = &linkedList.len;
         Return;
      End-If;
   End-If;
   Local COMMON:util:entity:LinkedNode &node = &linkedList.getLastNode();
   %This.firstNode.previousNode = &node;
   &node.nextNode = %This.firstNode;
   %This.firstNode = &linkedList.getFirstNode();
   %This.size = %This.size + &linkedList.len;
end-method;

method set
   /+ &index as Integer, +/
   /+ &element as Any +/
   Local COMMON:util:entity:LinkedNode &node = create COMMON:util:entity:LinkedNode(&element);
   %This.setNode(&index, &node);
end-method;

method setNode
   /+ &index as Integer, +/
   /+ &node as COMMON:util:entity:LinkedNode +/
   If &index = 1 Then
      %This.firstNode.previousNode = &node;
      &node.previousNode = Null;
      &node.nextNode = %This.firstNode;
      %This.firstNode = &node;
   Else
      Local COMMON:util:entity:LinkedNode &node2 = %This.getNode(&index);
      Local COMMON:util:entity:LinkedNode &node1 = &node2.previousNode;
      &node.previousNode = &node1;
      &node1.nextNode = &node;
      &node.nextNode = &node2;
      &node2.previousNode = &node;
   End-If;
   %This.size = %This.size + 1;
end-method;

method setLinkedList
   /+ &index as Integer, +/
   /+ &linkedList as COMMON:util:LinkedList +/
   If &linkedList.len = 0 Then
      Return;
   End-If;
   If &index = 1 Then
      Local COMMON:util:entity:LinkedNode &node = &linkedList.getLastNode();
      %This.firstNode.previousNode = &node;
      &node.nextNode = %This.firstNode;
      %This.firstNode = &linkedList.getFirstNode();
   Else
      Local COMMON:util:entity:LinkedNode &node2 = %This.getNode(&index);
      Local COMMON:util:entity:LinkedNode &node1 = &node2.previousNode;
      Local COMMON:util:entity:LinkedNode &nodeSet1 = &linkedList.getFirstNode();
      Local COMMON:util:entity:LinkedNode &nodeSet2 = &linkedList.getLastNode();
      &nodeSet1.previousNode = &node1;
      &node1.nextNode = &nodeSet1;
      &nodeSet2.nextNode = &node2;
      &node2.previousNode = &nodeSet2;
   End-If;
   %This.size = %This.size + &linkedList.len;
end-method;

method get
   /+ &index as Integer +/
   /+ Returns Any +/
   Return %This.getNode(&index).anyProperty;
end-method;

method getNode
   /+ &index as Integer +/
   /+ Returns COMMON:util:entity:LinkedNode +/
   If &index > %This.size Then
      throw CreateException(0, 0, "数组越界:&index-" | &index | "不在集合1到" | %This.size | "范围内");
   End-If;
   Local COMMON:util:entity:LinkedNode &node;
   Local integer &i;
   If (%This.size - &index) < &index Then /* &index靠后,从末尾开始查找 */
      &node = %This.lastNode;
      For &i = %This.size To 1 Step - 1
         If &index = &i Then
            Return &node;
         End-If;
         &node = &node.previousNode;
      End-For;
   Else /* &index靠前,从头部开始查找 */
      &node = %This.firstNode;
      For &i = 1 To %This.size
         If &index = &i Then
            Return &node;
         End-If;
         &node = &node.nextNode;
      End-For;
   End-If;
end-method;

method getFirst
   /+ Returns Any +/
   Return %This.firstNode.anyProperty;
end-method;

method getFirstNode
   /+ Returns COMMON:util:entity:LinkedNode +/
   Return %This.firstNode;
end-method;

method getLast
   /+ Returns Any +/
   Return %This.lastNode.anyProperty;
end-method;

method getLastNode
   /+ Returns COMMON:util:entity:LinkedNode +/
   Return %This.lastNode;
end-method;

method replace
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &element as Any +/
   Local COMMON:util:entity:LinkedNode &node = create COMMON:util:entity:LinkedNode(&element);
   %This.replaceNode(&startIndex, &endIndex, &node);
end-method;

method replaceNode
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &node as COMMON:util:entity:LinkedNode +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local COMMON:util:entity:LinkedNode &node2 = %This.get(&endIndex).nextNode;
   Local COMMON:util:entity:LinkedNode &node1 = %This.get(&startIndex).previousNode;
   If &node2 = Null Then
      %This.lastNode = &node;
   Else
      &node2.previousNode = &node;
   End-If;
   &node.nextNode = &node2;
   &node.previousNode = &node1;
   If &node1 = Null Then
      %This.firstNode = &node;
   Else
      &node1.nextNode = &node;
   End-If;
   %This.size = %This.size + &endIndex - &startIndex + 2;
end-method;

method replaceToLinkedList
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer, +/
   /+ &linkedList as COMMON:util:LinkedList +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local COMMON:util:entity:LinkedNode &node2 = %This.get(&endIndex).nextNode;
   Local COMMON:util:entity:LinkedNode &node1 = %This.get(&startIndex).previousNode;
   Local COMMON:util:entity:LinkedNode &nodeR2 = &linkedList.getLastNode();
   Local COMMON:util:entity:LinkedNode &nodeR1 = &linkedList.getFirstNode();
   If &node2 = Null Then
      %This.lastNode = &nodeR2;
   Else
      &node2.previousNode = &nodeR2;
   End-If;
   &nodeR2.nextNode = &node2;
   &nodeR1.previousNode = &node1;
   If &node1 = Null Then
      %This.firstNode = &nodeR1;
   Else
      &node1.nextNode = &nodeR1;
   End-If;
   %This.size = %This.size + &endIndex - &startIndex + 1 + &linkedList.len;
end-method;

method interceptList
   /+ &startIndex as Integer, +/
   /+ &endIndex as Integer +/
   If &startIndex > &endIndex Then
      Local integer &i = &startIndex;
      &startIndex = &endIndex;
      &endIndex = &i;
   End-If;
   Local COMMON:util:entity:LinkedNode &node1 = %This.get(&startIndex);
   Local COMMON:util:entity:LinkedNode &node2 = %This.get(&endIndex);
   %This.firstNode = &node1;
   %This.lastNode = &node2;
   %This.firstNode.previousNode = Null;
   %This.lastNode.nextNode = Null;
   %This.size = &endIndex - &startIndex + 1;
end-method;

method reverse
   /* Local COMMON:util:entity:LinkedNode &node1 = %This.firstNode;
   %This.firstNode = %This.lastNode;
   %This.lastNode = &node1;
   Local integer &i;
   Local COMMON:util:entity:LinkedNode &node2 = &node1.nextNode;
   Local COMMON:util:entity:LinkedNode &node3;
   For &i = 1 To %This.size
      If &node2 = Null Then
         Break;
      End-If;
      &node3 = &node2.nextNode;
      &node2.nextNode = &node1;
      &node1.previousNode = &node2;
      &node1 = &node2;
      &node2 = &node3;
   End-For;
   %This.firstNode.previousNode = Null;
   %This.lastNode.nextNode = Null; */
   Local COMMON:util:entity:LinkedNode &nodeLeft = %This.firstNode;
   Local COMMON:util:entity:LinkedNode &nodeRight = %This.lastNode;
   Local integer &i = 1;
   Local any &any;
   While True
      If &i * 2 > %This.size Then
         Return;
      End-If;
      &any = &nodeLeft.anyProperty;
      &nodeLeft.anyProperty = &nodeRight.anyProperty;
      &nodeRight.anyProperty = &any;
      &nodeLeft = &nodeLeft.nextNode;
      &nodeRight = &nodeRight.previousNode;
      &i = &i + 1;
   End-While;
end-method;

method exchange
   /+ &index1 as Integer, +/
   /+ &index2 as Integer +/
   Local COMMON:util:entity:LinkedNode &node1 = %This.get(&index1);
   Local COMMON:util:entity:LinkedNode &node2 = %This.get(&index2);
   Local any &any = &node1.anyProperty;
   &node1.anyProperty = &node2.anyProperty;
   &node2.anyProperty = &any;
end-method;

method remove
   /+ &index as Integer +/
   If &index = 1 Then
      %This.removeFirst();
      Return;
   Else
      If &index = %This.size Then
         %This.removeLast();
         Return;
      End-If;
   End-If;
   Local COMMON:util:entity:LinkedNode &node = %This.get(&index);
   &node.previousNode.nextNode = &node.nextNode;
   &node.nextNode.previousNode = &node.previousNode;
   %This.size = %This.size - 1;
end-method;

method removeFirst
   If %This.size < 2 Then
      %This.firstNode = Null;
      %This.lastNode = Null;
      %This.size = 0;
   Else
      %This.firstNode = %This.firstNode.nextNode;
      %This.firstNode.previousNode = Null;
      %This.size = %This.size - 1;
   End-If;
end-method;

method removeLast
   If %This.size < 2 Then
      %This.firstNode = Null;
      %This.lastNode = Null;
      %This.size = 0;
   Else
      %This.lastNode = %This.lastNode.previousNode;
      %This.lastNode.nextNode = Null;
      %This.size = %This.size - 1;
   End-If;
end-method;

method getSize
   /+ Returns Integer +/
   Return %This.size;
end-method;

method initializePointerToFirst
   %This.pointer = %This.firstNode;
end-method;

method initializePointerToLast
   %This.pointer = %This.lastNode;
end-method;

method initializePointerToIndex
   /+ &index as Integer +/
   %This.pointer = %This.getNode(&index);
end-method;

method hasNext
   /+ Returns Boolean +/
   Return (%This.pointer <> Null);
end-method;

method next
   /+ Returns COMMON:util:entity:LinkedNode +/
   Local COMMON:util:entity:LinkedNode &nd = %This.pointer;
   %This.pointer = %This.pointer.nextNode;
   Return &nd.anyProperty ;
end-method;

method hasPrevious
   /+ Returns Boolean +/
   Return (%This.pointer <> Null);
end-method;

method previous
   /+ Returns COMMON:util:entity:LinkedNode +/
   Local COMMON:util:entity:LinkedNode &nd = %This.pointer;
   %This.pointer = %This.pointer.previousNode;
   Return &nd.anyProperty ;
end-method;

LinkedNode类:

/* 此类是一个链表集合节点实体类 */

class LinkedNode
   /* 上一个节点 */
   property GT_COMMON:UTIL:entity:LinkedNode previousNode;
   /* 下一个节点 */
   property GT_COMMON:UTIL:entity:LinkedNode nextNode;
   
   /* 存放节点信息 */
   property any anyProperty;
   
   method LinkedNode(&property As any);
end-class;

method LinkedNode
   /+ &property as Any +/
   %This.anyProperty = &property;
end-method;

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值