博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构-链表
阅读量:5994 次
发布时间:2019-06-20

本文共 12773 字,大约阅读时间需要 42 分钟。

数据结构-链表

链表特点

  • 链表是一种用于存储数据集合的数据结构
  • 相邻元素之间通过指针连接
  • 最后一个元素的后继指针值为 NULL
  • 链表的空间能够按需分配
  • 没有内存空间的浪费
  • 链表的长度可以增加或缩小

链表抽象数据类型操作

  • 插入
  • 删除
  • 删除链表
  • 链表长度
  • 查找

链表特点

  • 优点:可以常数时间内动态分配储存空间
  • 缺点:储存和查找数据开销大

单向链表

  • 特点:链表通常指单向链表,包含多个结点,每个结点有一个指向后继元素的 next 指针,表中最后一个结点的 next 指针值为 NULL,表示链表的结束。
  • 单向列表的实现

    public class ListNode {      private Object data;      private ListNode nextNode;      public ListNode(Object data) {          this.data = data;          this.nextNode = null;      }      public void setNext(ListNode node) {          nextNode = node;      }      public ListNode getNext() {          return nextNode;      }      public void setData(Object d) {          this.data = d;      }      public Object getData() {          return data;      }      /***       * 链表的遍历       * @return 链表的长度       */      public int getListNodeLength() {          int length = 0;          ListNode tempNode = this;          while (tempNode != null) {              length++;              tempNode = tempNode.getNext();          }          return length;      }      public ListNode insert(ListNode nodeToInsert) {          if (this == null) {              return nodeToInsert;          } else {              ListNode temNode = this;              while (temNode.getNext() != null) {                  temNode = temNode.getNext();              }              temNode.setNext(nodeToInsert);              return this;          }      }      /***       * 在链表中插入结点,分为开头,中间,或者结尾       * @param nodeToInsert: 插入的结点       * @param position:位置       * @return 插入以后的链表       */      ListNode insertInLinkedList(ListNode nodeToInsert, int position) {          if (this == null) {              return nodeToInsert;          }          int size = getListNodeLength();          if (position > size + 1 || position < 1) {              throw new PositionInvalidException("Position of node to insert is invalid ,The valid inputs are 1 to " + (size + 1));          }          if (position == 1) {   //在链表开头插入结点              nodeToInsert.setNext(this);              return nodeToInsert;          } else {  //在链表中间或者结尾插入结点,需要得到插入位置的前一个位置的结点,同时拿到插入位置的结点,把要插入的结点的下一个结点指向当前位置的结点,前一个位置的结点的下一个结点指向要插入的结点,完成结点的插入操作。              ListNode tempNode = this;              int count = 1;              while (count < position - 1) {                  tempNode = tempNode.getNext();                  count++;              }              ListNode currentNode = tempNode.getNext();              nodeToInsert.setNext(currentNode);              tempNode.setNext(nodeToInsert);          }          return this;      }      /***       * 删除节点       * @param deleteNode:需要删除的节点       * @return       */      public ListNode deleteNode(ListNode deleteNode) {          ListNode listNode = this;          Object data = deleteNode.getData();          if (listNode == null) {              throw new NullPointerException("listNode is empty");          }          ListNode tempNode = listNode;          ListNode previousNode = null;          while (tempNode != null) {              if (tempNode.getData().equals(data)) {                  if (previousNode == null) {                      listNode = tempNode.getNext();                      tempNode = null;                  } else {                      previousNode.setNext(tempNode.getNext());                  }                  return listNode;              }              previousNode = tempNode;              tempNode = tempNode.getNext();          }          throw new NodeNotFoundException("This Node is not found in LinkedList");      }      /**       * 删除链表指定位置的结点,分为从开头删除,中间和结尾删除       *       * @param headNode:链表       * @param position:删除结点的位置       * @return 删除以后的链表       */      ListNode deleteNodeFromLinkedList(ListNode headNode, int position) {          int length = getListNodeLength();          if (position < 1 || position > length) {              throw new PositionInvalidException("position is out of listNode");          }          if (position == 1) {  //删除位置在链表开头              ListNode tempNode = headNode.getNext();              headNode = null;              return tempNode;          } else {  //删除位置在链表中间或者结尾              ListNode tempNode = headNode;              int count = 1;              while (count < position) {                  tempNode = tempNode.getNext();                  count++;              }              ListNode currentNode = tempNode.getNext();              tempNode.setNext(currentNode.getNext());              currentNode = null;              return tempNode;          }      }      /***       * 删除单向链表       * @param headNode:链表       */      void deleteLinkedList(ListNode headNode) {          ListNode auxilary, iterator = headNode;          while (iterator != null) {              auxilary = iterator.getNext();              iterator = null;              iterator = auxilary;          }      }      /***       * 打印单链表       * @return       */      @Override      public String toString() {          StringBuilder sb = new StringBuilder();          if (this != null) {              sb.append("ListNode:(" + this.getListNodeLength() + "){ \n");              int node = 0;              ListNode temp = this;              while (temp != null) {                  node++;                  sb.append("  nodeNumber:" + node + ",nodeData:" + temp.getData() + "\n");                  temp = temp.getNext();              }              sb.append(" }");          }          return sb.toString();      }  }

双向链表

  • 特点
    • 比单向列表多一个前驱结点指针
    • 插入和删除更加费时
    • 添加一个指针,需要额外的空间开销
  • 实现

    public class DLLNode {              private Object data;              private DLLNode next;              private DLLNode previous;              public DLLNode(Object data) {                  this.data = data;              }              public Object getData() {                  return data;              }              public void setData(Object data) {                  this.data = data;              }              public DLLNode getNext() {                  return next;              }              public void setNext(DLLNode next) {                  this.next = next;              }              public DLLNode getPrevious() {                  return previous;              }              public void setPrevious(DLLNode previous) {                  this.previous = previous;              }              /***               * 获取双向链表的长度               * @param headNode:双向链表               * @return               */              public int getDLLNodeLength(DLLNode headNode) {                  DLLNode nextNode = headNode;                  int length = 0;                  while (nextNode.getNext() != null) {                      nextNode = nextNode.getNext();                      length++;                  }                  return length;              }              /***               * 双向链表插入               * @param headNode:双向链表               * @param nodeToInsert:待插入结点               * @param position:位置               * @return 插入后的双向链表               */              public DLLNode insert(DLLNode headNode, DLLNode nodeToInsert, int position) {                  if (headNode == null) {                      return nodeToInsert;                  }                  int length = getDLLNodeLength(headNode);                  if (position > length + 1 || position < 1) {                      System.out.println("Position of nodeToInsert is invalid ," + "The valid inputs are 1 to " + (length + 1));                      return headNode;                  }                  if (position == 1) {  //在链表开头插入                      headNode.setPrevious(nodeToInsert);                      nodeToInsert.setNext(headNode);                      nodeToInsert.setPrevious(null);                      return nodeToInsert;                  } else { // 在链表中间或者尾部插入                      DLLNode tempNode = headNode;                      int count = 1;                      while (count < length - 1) {                          tempNode = tempNode.getNext();                          count++;                      }                      DLLNode currentNode = tempNode.getNext();                      nodeToInsert.setNext(currentNode);                      if (currentNode != null) {                          currentNode.setPrevious(nodeToInsert);                      }                      tempNode.setNext(nodeToInsert);                      nodeToInsert.setPrevious(tempNode);                  }                  return headNode;              }              public DLLNode delete(DLLNode headNode, int position) {                  int size = getDLLNodeLength(headNode);                  if (position > size || position < 1) {                      System.out.println("Position of node to delete is invalid , The valid inputs are 1 to " + (size + 1));                      return headNode;                  }                  if (position == 1) { //删除双向链表的第一个位置                      DLLNode tempNode = headNode.getNext();                      tempNode.setPrevious(null);                      headNode = null;                      return tempNode;                  } else {  //删除双向链表的位置在中间或者最后                      DLLNode previousNode = headNode;                      int count = 1;                      while (count < position - 1) {                          previousNode = previousNode.getNext();                          count++;                      }                      DLLNode currentNode = previousNode.getNext();                      DLLNode laterNode = currentNode.getNext();                      previousNode.setNext(laterNode);                      if (laterNode != null)                          laterNode.setPrevious(previousNode);                      currentNode = null;                  }                  return headNode;              }          }

循环列表

  • 特点
    • 没有结束标志
    • 最后一个结点的 next 指向头结点
  • 实现

    public class CLLNode {      private Object data;      private CLLNode next;      public Object getData() {          return data;      }      public void setData(Object data) {          this.data = data;      }      public CLLNode getNext() {          return next;      }      public void setNext(CLLNode next) {          this.next = next;      }      /***       * 遍历循环链表       * @param headNode       * @return:链表的长度       */      public int circularListLength(CLLNode headNode) {          int length = 0;          CLLNode currentNode = headNode;          while (currentNode != null) {              length++;              currentNode = currentNode.getNext();              if (currentNode == headNode) {                  break;              }          }          return length;      }      /***       * 在循环列表最后插入一个结点       * @param headNode       * @param nodeToInsert       * @return       */      public CLLNode insertAtEndInCLLNode(CLLNode headNode, CLLNode nodeToInsert) {          nodeToInsert.setNext(nodeToInsert);          if (headNode == null) {              return nodeToInsert;          }          CLLNode currentNode = headNode;          while (currentNode.getNext() != headNode) {              currentNode.setNext(currentNode.getNext());          }          currentNode.setNext(nodeToInsert);          nodeToInsert.setNext(headNode);          return headNode;      }      /***       * 在循环列表的开始位置插入节点       * @param headNode       * @param nodeToInsert       * @return       */      public CLLNode insertAtBeginInCLLNode(CLLNode headNode, CLLNode nodeToInsert) {          nodeToInsert.setNext(nodeToInsert);          if (headNode == null) {              return nodeToInsert;          }          CLLNode currentNode = headNode;          while (currentNode.getNext() != headNode) {              currentNode.setNext(currentNode.getNext());          }          nodeToInsert.setNext(headNode);          currentNode.setNext(nodeToInsert);          return nodeToInsert;      }      /***       * 删除循环列表的最后一个节点       * @param headNode       * @return       */      public CLLNode deleteLastNodeFromCLLNode(CLLNode headNode) {          if (headNode == null) {              return null;          }          CLLNode tempNode = headNode;          CLLNode currentNode = headNode;          while (currentNode.getNext() != headNode) {              tempNode = currentNode;              currentNode = currentNode.getNext();          }          tempNode.setNext(headNode);          currentNode = null;          return headNode;      }      /***       * 删除循环列表的头结点       * @param headNode       * @return       */      public CLLNode deleteFrontNodeFormCLLNode(CLLNode headNode) {          if (headNode == null) {              return null;          }          CLLNode currentNode = headNode;          while (currentNode.getNext() != headNode) {              currentNode = currentNode.getNext();          }          CLLNode secondNode = headNode.getNext();          currentNode.setNext(secondNode);          return secondNode;      }  }

转载地址:http://qntlx.baihongyu.com/

你可能感兴趣的文章
详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载
查看>>
按的第一个greasemonkey插件:评论时可以粘贴啦~~
查看>>
一维数组的遍历 .
查看>>
不可恢复的生成错误mergemod.dll 2.0.2600.0
查看>>
Levenshtein Distance (编辑距离) 算法详解
查看>>
WPF学习笔记 - 在XAML里绑定
查看>>
JAVA中字符串比較equals()和equalsIgnoreCase()的差别
查看>>
深入了解Java虚拟机
查看>>
验证 Xcode 是否来自正规渠道
查看>>
企业视觉-大型电商(制)-高性能的用户视觉性能(1)
查看>>
高效实现 std::string split() API
查看>>
每天一个linux命令(21):find命令之xargs
查看>>
仿Google首页搜索自动补全
查看>>
报文首部
查看>>
【Nginx】启动过程
查看>>
Centos7下卸载docker
查看>>
libXext.so.6 libXp.so.6 libXt.so.6 is needed by openmotif21-2.1.30-11.el7.i686
查看>>
C# 强制关闭当前程序进程(完全Kill掉不留痕迹)
查看>>
hadoop中联结不同来源数据
查看>>
Consolidated Seed Table Upgrade Patch(Patch 17204589)
查看>>