python数据结构学习笔记-2016-11-26-01-链表排序
2016-12-31 18:49
846 查看
12.5 链表排序
12.5.1 插入排序
将原链表的每一个结点取出,放入到新的排序链表中。
12.5.2 归并排序
与之前序列的归并排序不同的是,链表的归并排序并不需要包装函数,因为只需传入链表的头指针即可。我们要注意的是两个辅助方法。
_splitLinkedList()将原链表分割成两部分,尤其值得注意的是两个外部指针midPoint和curNode的移动,后者的移动速度是前者的两倍,当curNode移动至链表末尾时,midPoint正好指向链表的中间位置,再将右半部分的头指针设置为midPoint的下一个结点即可,左半部分的头指针仍是原来的头指针,最后将两者分开即可。
再看另一个辅助方法_mergeLinkedLists(),该方法主要是将两个排好序的链表合并。它使用尾指针的目的在于,在链表的末尾补插元素(元素从小到大排列)只需要O(1)的时间复杂度。此外,该方法还使用了假结点(dummy node),假结点是数据域为None的结点,使用它可以在插入或删除结点时避免使用if来分情况讨论(?)。
12.5.1 插入排序
将原链表的每一个结点取出,放入到新的排序链表中。
#-*-coding: utf-8-*- # 链表的插入排序 def llistInsertionSort(origList): # 确保链表非空 if origList is None: return # 对原链表遍历 newList = None while origList is not None: # 临时外部指针 curNode = origList # 移动原链表的头指针 origList = origList.next # 将结点从原链表中抽离,并放入到新的排序链表中 curNode.next = None newList = addToSortedList(newList, curNode) return newList def addToSortedList(head, node): predNode = None curNode = head while curNode is not None and node.data > curNode.data: predNode = curNode curNode = curNode.next node.next = curNode if curNode is head: head = node else: predNode.next = node与python列表类似,其时间复杂度也是O(n²)。不同之处在于,不需要像列表那样,对每一个元素进行移位。
12.5.2 归并排序
#-*-coding: utf-8-*- # 链表的归并排序 def llistMergeSort(theList): # 如果链表为空,即递归终止条件,返回None if theList is None: return None # 分割链表成两部分 rightList = _splitLinkedList(theList) leftList = theList # 对左半部分链表分割 leftList = llistMergeSort(leftList) # 对右半部分分割 rightList = llistMergeSort(rightList) # 合并两个排好序的子链表 theList = _mergeLinkedLists(leftList, rightList) return theList # 分割链表,返回右半部分链表的头指针,左半部分链表的头指针,仍然是原链表的头指针 def _splitLinkedList(subList): # 临时外部指针,分别指向第一和第二个结点 midPoint = subList curNode = midPoint.next # 对原链表进行遍历,curNode的移动速度是midPoint的两倍,当curNode移动至原链表末尾时,此时midPoint正好移动到链表中间的位置 while curNode is not None: curNode = curNode.next if curNode is not None: midPoint = midPoint.next curNode = curNode.next rightList = midPoint.next # 设置右半部分链表的头指针 midPoint.next = None # 将右半部分链表从原链表中分离 return rightList # 合并两个排好序的子链表 def _mergeLinkedLists(subListA, subListB): # 创建假结点 newList = ListNode(None) newTail = newList # 向新链表补插入subListA和subListB的结点,直到遍历完其中一个链表为止 while subListA is not None and subListB is not None: if subListA.data <= subListB.data: newTail.next = subListA subListA = subListA.next else: newTail.next = subListB subListB = subListB.next newTail = newTail.next newTail.next = None # 将另一个链表的剩余部分,也添加到新链表中来 if subListA is not None: newTail.next = subListA else: newTail.next = subListB # 返回假结点的下一个结点 return newList.next
与之前序列的归并排序不同的是,链表的归并排序并不需要包装函数,因为只需传入链表的头指针即可。我们要注意的是两个辅助方法。
_splitLinkedList()将原链表分割成两部分,尤其值得注意的是两个外部指针midPoint和curNode的移动,后者的移动速度是前者的两倍,当curNode移动至链表末尾时,midPoint正好指向链表的中间位置,再将右半部分的头指针设置为midPoint的下一个结点即可,左半部分的头指针仍是原来的头指针,最后将两者分开即可。
再看另一个辅助方法_mergeLinkedLists(),该方法主要是将两个排好序的链表合并。它使用尾指针的目的在于,在链表的末尾补插元素(元素从小到大排列)只需要O(1)的时间复杂度。此外,该方法还使用了假结点(dummy node),假结点是数据域为None的结点,使用它可以在插入或删除结点时避免使用if来分情况讨论(?)。
相关文章推荐
- python数据结构学习笔记-2016-10-28-01-带尾指针的链表和排序链表
- python数据结构学习笔记-2016-10-27-01-链表
- python数据结构学习笔记-2016-11-07-01-双链表
- python数据结构学习笔记-2016-11-24-01-快速排序
- python数据结构学习笔记-2016-10-24-01-排序列表
- python数据结构学习笔记-2016-11-23-01-归并排序
- python数据结构学习笔记-2016-10-22-01-评价python列表
- python数据结构学习笔记-2016-10-28-02-使用链表实现稀疏矩阵
- python数据结构学习笔记-2016-10-17-01-集合
- python数据结构学习笔记-2016-11-26-02-树结构
- python数据结构学习笔记-2016-10-05-01-抽象数据类型(一)
- python数据结构学习笔记-2016-11-30-01-堆
- python数据结构学习笔记-2016-10-15-01-矩阵ADT
- python数据结构学习笔记-2016-11-20-01-直方图ADT
- python数据结构学习笔记-2016-11-07-03-多重链表以及相应的迭代器
- python数据结构学习笔记-2016-11-18-01-散列表ADT
- python数据结构学习笔记-2016-10-07-01-完善后的mydate.py
- python数据结构学习笔记-2016-11-05-01-队列ADT及其实现
- python数据结构学习笔记-2016-10-23-02-排序
- python数据结构学习笔记-2016-12-04-01-Morse电码