func Test_InitSorted(t *testing.T) { data := sort.IntSlice{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} tree := Tree{} tree.InitSorted(data.Len()) check(t, data, &tree, tree.root) check_iter(t, data, &tree) data = sort.IntSlice{} f := map[int]struct{}{} tree = Tree{} for i := 100; i > 0; i-- { v := rand.Intn(1000) if _, ok := f[v]; ok { continue } data = append(data, v) } sort.Sort(data) tree.InitSorted(data.Len()) check(t, data, &tree, tree.root) check_iter(t, data, &tree) }
//Be careful to use same partioning as in lecture //and return total number of comparisons func Quicksort(input sort.IntSlice, ps pivotSelector) int { if input.Len() < 2 { return 0 } input.Swap(0, ps(input)) i := 1 for j := 1; j < input.Len(); j++ { if input.Less(j, 0) { input.Swap(i, j) i++ } } input.Swap(0, i-1) comparisons := input.Len() - 1 comparisons += Quicksort(input[:i-1], ps) comparisons += Quicksort(input[i:], ps) return comparisons }
func (f *File) saveUsingXrefStream() error { info, err := os.Stat(f.filename) if err != nil { return err } file, err := os.OpenFile(f.filename, os.O_RDWR|os.O_APPEND, 0666) if err != nil { return err } defer func() { err := file.Close() if err != nil { panic(err) } }() offset := info.Size() + 1 n, err := writeLineBreakTo(file) if err != nil { return err } offset += n xrefs := map[Integer]crossReference{} xrefs[0] = crossReference{0, 0, 65535} free := sort.IntSlice{0} for i := range f.objects { switch typed := f.objects[i].(type) { case crossReference: // no-op, don't need to write unchanged objects to file // however, we do need to handle the free list // xrefs[Integer(i)] = typed if typed[0] == 0 { free = append(free, int(i)) } case IndirectObject: xrefs[Integer(i)] = crossReference{1, uint(offset - 1), typed.GenerationNumber} n, err = typed.writeTo(file) if err != nil { return err } offset += n n, err = writeLineBreakTo(file) if err != nil { return err } offset += n case freeObject: xrefs[Integer(i)] = crossReference{0, 0, uint(typed)} free = append(free, int(i)) default: panic(fmt.Sprintf("unhandled type: %T", typed)) } } // Figure out the highest object number to set Size properly var maxObjNum uint for objNum := range f.objects { if objNum > maxObjNum { maxObjNum = objNum } } // add an xref for the xrefstream xrefstreamObjectNumber := uint(maxObjNum + 1) maxObjNum++ xref := crossReference{1, uint(offset - 1), 0} xrefs[Integer(xrefstreamObjectNumber)] = xref f.objects[xrefstreamObjectNumber] = xref // fill in the free linked list free.Sort() for i := 0; i < free.Len()-1; i++ { xref := xrefs[Integer(free[i])] xref[1] = uint(free[i+1]) xrefs[Integer(free[i])] = xref } objects := make(sort.IntSlice, 0, len(xrefs)) for objectNumber := range xrefs { objects = append(objects, int(objectNumber)) } objects.Sort() // group into consecutive sets groups := []sort.IntSlice{} groupStart := 0 for i := range objects { if i == 0 { continue } if objects[i] != objects[i-1]+1 { groups = append(groups, objects[groupStart:i]) groupStart = i } } groups = append(groups, objects[groupStart:]) // Create the xrefstream dictionary (the trailer) trailer := Dictionary{} trailer[Name("Size")] = Integer(maxObjNum + 1) // Prev if f.prev != 0 { trailer[Name("Prev")] = f.prev } // Root trailer[Name("Root")] = f.Root // Encrypt if len(f.Encrypt) != 0 { trailer[Name("Encrypt")] = f.Encrypt } // Info if f.Info.ObjectNumber != 0 { trailer[Name("Info")] = f.Info } // ID if len(f.ID) != 0 { trailer[Name("ID")] = f.ID } // Add xrefstream specific things to trailer trailer["Type"] = Name("XRef") // Index index := Array{} // fmt.Println(groups) for _, group := range groups { index = append(index, Integer(group[0]), Integer(len(group))) } trailer["Index"] = index // layout for the stream (W) maxXref := [3]uint{} for _, xref := range xrefs { for i := 0; i < len(xref); i++ { if xref[i] > maxXref[i] { maxXref[i] = xref[i] } } } nBytes := [3]int{} for i := range nBytes { nBytes[i] = nBytesForInt(int(maxXref[i])) } trailer["W"] = Array{Integer(nBytes[0]), Integer(nBytes[1]), Integer(nBytes[2])} // log.Println(xrefs) stream := &bytes.Buffer{} for _, group := range groups { for _, objectNumber := range group { xref := xrefs[Integer(objectNumber)] for i := range xref { _, err = stream.Write(intToBytes(xref[i], nBytes[i])) if err != nil { return err } } } } xrefstream := IndirectObject{ ObjectReference: ObjectReference{ ObjectNumber: xrefstreamObjectNumber, }, Object: Stream{ Dictionary: trailer, Stream: stream.Bytes(), }, } _, err = f.Add(xrefstream) if err != nil { return err } _, err = xrefstream.writeTo(file) if err != nil { return err } fmt.Fprintf(file, "\nstartxref\n%d\n%%%%EOF", offset-1) return nil }
func (f *File) saveUsingXrefTable() error { info, err := os.Stat(f.filename) if err != nil { return err } file, err := os.OpenFile(f.filename, os.O_WRONLY|os.O_APPEND, 0666) if err != nil { return err } defer func() { err := file.Close() if err != nil { panic(err) } }() offset := info.Size() + 1 n, err := writeLineBreakTo(file) if err != nil { return err } offset += n xrefs := map[Integer]crossReference{} xrefs[0] = crossReference{0, 0, 65535} free := sort.IntSlice{} for i := range f.objects { switch typed := f.objects[i].(type) { case crossReference: // no-op, don't need to write unchanged objects to file // however, we do need to handle the free list // xrefs[Integer(i)] = typed if typed[0] == 0 { free = append(free, int(i)) } case IndirectObject: xrefs[Integer(i)] = crossReference{1, uint(offset - 1), typed.GenerationNumber} n, err = typed.writeTo(file) if err != nil { return err } offset += n n, err = writeLineBreakTo(file) if err != nil { return err } offset += n case freeObject: xrefs[Integer(i)] = crossReference{0, 0, uint(typed)} free = append(free, int(i)) default: panic(fmt.Sprintf("unhandled type: %T", typed)) } } // fill in the free linked list free.Sort() for i := 0; i < free.Len()-1; i++ { xref := xrefs[Integer(free[i])] xref[1] = uint(free[i+1]) xrefs[Integer(free[i])] = xref } objects := make(sort.IntSlice, 0, len(xrefs)) for objectNumber := range xrefs { objects = append(objects, int(objectNumber)) } objects.Sort() // group into consecutive sets groups := []sort.IntSlice{} groupStart := 0 for i := range objects { if i == 0 { continue } if objects[i] != objects[i-1]+1 { groups = append(groups, objects[groupStart:i]) groupStart = i } } // add remaining group groups = append(groups, objects[groupStart:]) // write as an xref table to file fmt.Fprintf(file, "xref\n") for _, group := range groups { fmt.Fprintf(file, "%d %d\n", group[0], len(group)) for _, objectNumber := range group { xref := xrefs[Integer(objectNumber)] fmt.Fprintf(file, "%010d %05d ", xref[1], xref[2]) switch xref[0] { case 0: // f entries fmt.Fprintf(file, "f\r\n") case 1: // n entries fmt.Fprintf(file, "n\r\n") case 2: panic("can't be in xref table") default: panic("unhandled case") } } } // Setup create the trailer fmt.Fprintf(file, "\ntrailer\n") trailer := Dictionary{} // Size // Figure out the highest object number to set Size properly var maxObjNum uint for objNum := range f.objects { if objNum > maxObjNum { maxObjNum = objNum } } trailer[Name("Size")] = Integer(maxObjNum + 1) // Prev if f.prev != 0 { trailer[Name("Prev")] = f.prev } // Root trailer[Name("Root")] = f.Root // Encrypt if len(f.Encrypt) != 0 { trailer[Name("Encrypt")] = f.Encrypt } // Info if f.Info.ObjectNumber != 0 { trailer[Name("Info")] = f.Info } // ID if len(f.ID) != 0 { trailer[Name("ID")] = f.ID } _, err = trailer.writeTo(file) if err != nil { return err } fmt.Fprintf(file, "\nstartxref\n%d\n%%%%EOF", offset-1) return nil }