// Sort a linked list. This is a stable sort. func SortList(List *list.List, f SortLtFunc) { var L, R, N, A, T *list.Element var sz uint = 1 var numMerges, Lsz, Rsz uint if List.Len() < 2 { return } A = List.Front() //Z = List.Back() (not needed) // STABLE for { // 'A' is either the head of the original list (on the first iteration), or // a list whose subdivisions of 2*(sz/2) are sorted. Either way, 'A' is now // 'L' and 'A' and 'T' will be used to assemble the next 'generation' of // the sorted list. numMerges = 0 L = A A = nil T = A for L != nil { numMerges++ R = L Lsz = 0 Rsz = sz // Step R so that we have adjacent but non-overlapping partitions // [L,R) (range Lsz) // and // [R,R+Rsz) (range Rsz) // The union of which covers completely the subsection of the list // [L,R+Rsz) (range of up to 2*sz) // which is the part of the list which we are sorting at the moment. // // After this Lsz == Rsz and our partitions are of equal size, unless !R // in which case the partitions may be unequal. for R != nil && Lsz < sz { Lsz++ R = R.Next() } // MERGE // So, as long as either the L-list is non-empty (Lsz > 0) // or the R-list is non-empty (Rsz > 0 and R points to something // non-NULL), we have things to merge in our biparted list subsection. // for Lsz > 0 || (Rsz > 0 && R != nil) { // Choose which list to take the next element from. // If either list is empty, we must choose from the other one. // // In any case, the list taken from is moved up and its size // decremented. // // N identifies the new item to be added to the sorted list. // if Lsz == 0 { // The L-side is empty; choose from R. N = R R = R.Next() Rsz-- } else if Rsz == 0 || R == nil { // The R-side is empty; choose from L. N = L L = L.Next() Lsz-- } else if f(R, L) { // If both lists are non-empty, compare the first element of each and // choose the lower one. N = R R = R.Next() Rsz-- } else { // "If the first elements compare equal, choose from the L-side." N = L L = L.Next() Lsz-- } if T != nil { // "NEXT(T) = N" List.MoveAfter(N, T) } else { A = N } // "PREV(N) = T"; this is taken care of by MoveAfter // N is now the tail. T = N } // Now A (with tail T) is a completely sorted list of the sublist. // We have advanced L until it is where R started out, and we have // advanced R until it is pointing at the next pair of length-K lists to // merge. So set L to the value of R, and go back to the start of this // loop. L = R } // Now we have gone through the entire list forming biparted sublists of // sizes (up to) 2*sz. It is time to move "up" by doubling sz and merging // again. // // We keep track of Z so we can set//tail at the end, if necessary. // // Ensure the tail's next pointer is properly NULLed. //NEXT(T)=nil //Z = T (not needed) sz = sz * 2 if numMerges <= 1 { break } } }
func mv(l *list.List, args []string) { switch len(args) { case 0: fmt.Println("What item do you want to move?") os.Exit(1) case 1: fmt.Println("Too few arguments.") os.Exit(1) case 2: // Check if remaining args are integers nums := make([]int, len(args)) for i, a := range args { n, err := strconv.Atoi(a) if err != nil { fmt.Printf("%q is not an item number.\n", a) os.Exit(1) } nums[i] = n } // Make sure integers is not out of bounds if max(nums...) > l.Len() { fmt.Printf("item [%d] is out of bounds.\n", max(nums...)) os.Exit(1) } else if min(nums...) < 1 { fmt.Printf("item [%d] is out of bounds.\n", min(nums...)) os.Exit(1) } else if nums[0] == nums[1] { // Make sure numbers are different fmt.Println("Item alread in place.") os.Exit(1) } // Collect elements elements := make([]*list.Element, len(nums)) itemNumber, element := 1, l.Front() for itemNumber <= max(nums...) { if itemNumber == nums[0] { elements[0] = element } if itemNumber == nums[1] { elements[1] = element } element = element.Next() itemNumber++ } // Update date elements[0].Value.(ListItem)[DATE] = time.Now().Format(DATE_FORMAT) // Move item if nums[0] < nums[1] { // Use moveAfter l.MoveAfter(elements[0], elements[1]) } else { // Use moveBefore l.MoveBefore(elements[0], elements[1]) } fmt.Printf("Moving item:[%d] to location:[%d]\n", nums[0], nums[1]) default: fmt.Println("Too many arguments.") os.Exit(1) } }