数据结构与算法分析 C++版答案
数据结构与算法分析:C语言描述(原书第2版简体中文版!!!)PDF+源代码+习题答案
数据结构与算法分析:C语⾔描述(原书第2版简体中⽂版!!!)PDF+源代码+习题答案转⾃:/Linux/2014-04/99735.htm数据结构与算法分析:C语⾔描述(原书第2版中⽂版!!!) PDF+源代码+习题答案数据结构与算法分析:C语⾔描述(原书第2版)是《data structures and algorithm analysis in c》⼀书第2版的简体中译本。
原书曾被评为20世纪顶尖的30部计算机著作之⼀,作者mark allen weiss在数据结构和算法分析⽅⾯卓有建树,他的数据结构和算法分析的著作尤其畅销,并受到⼴泛好评.已被世界500余所⼤学⽤作教材。
在本书中,作者更加精炼并强化了他对算法和数据结构⽅⾯创新的处理⽅法。
通过c程序的实现,着重阐述了抽象数据类型的概念,并对算法的效率、性能和运⾏时间进⾏了分析。
数据结构与算法分析:C语⾔描述(原书第2版) PDF下载:百度⽹盘免费下载地址:(本⼈是从这⾥下载的,感谢原博主)全书特点如下: ●专⽤⼀章来讨论算法设计技巧,包括贪婪算法、分治算法、动态规划、随机化算法以及回溯算法 ●介绍了当前流⾏的论题和新的数据结构,如斐波那契堆、斜堆、⼆项队列、跳跃表和伸展树 ●安排⼀章专门讨论摊还分析,考查书中介绍的⼀些⾼级数据结构 ●新开辟⼀章讨论⾼级数据结构以及它们的实现,其中包括红⿊树、⾃顶向下伸展树。
treap树、k-d树、配对堆以及其他相关内容 ●合并了堆排序平均情况分析的⼀些新结果⽬录出版者的话专家指导委员会译者序前⾔第1章引论第2章算法分析第3章表、栈和队列第4章树第5章散列第6章优先队列(堆)第7章排序第8章不相交集ADT第9章图论算法第10章算法设计技巧第11章摊还分析第12章⾼级数据结构及其实现索引。
《数据结构与算法分析》(C++第二版)【美】Clifford A.Shaffer著 课后习题答案 二
《数据结构与算法分析》(C++第二版)【美】Clifford A.Shaffer著课后习题答案二5Binary Trees5.1 Consider a non-full binary tree. By definition, this tree must have some internalnode X with only one non-empty child. If we modify the tree to removeX, replacing it with its child, the modified tree will have a higher fraction ofnon-empty nodes since one non-empty node and one empty node have been removed.5.2 Use as the base case the tree of one leaf node. The number of degree-2 nodesis 0, and the number of leaves is 1. Thus, the theorem holds.For the induction hypothesis, assume the theorem is true for any tree withn − 1 nodes.For the induction step, consider a tree T with n nodes. Remove from the treeany leaf node, and call the resulting tree T. By the induction hypothesis, Thas one more leaf node than it has nodes of degree 2.Now, restore the leaf node that was removed to form T. There are twopossible cases.(1) If this leaf node is the only child of its parent in T, then the number ofnodes of degree 2 has not changed, nor has the number of leaf nodes. Thus,the theorem holds.(2) If this leaf node is the child of a node in T with degree 2, then that nodehas degree 1 in T. Thus, by restoring the leaf node we are adding one newleaf node and one new node of degree 2. Thus, the theorem holds.By mathematical induction, the theorem is correct.32335.3 Base Case: For the tree of one leaf node, I = 0, E = 0, n = 0, so thetheorem holds.Induction Hypothesis: The theorem holds for the full binary tree containingn internal nodes.Induction Step: Take an arbitrary tree (call it T) of n internal nodes. Selectsome internal node x from T that has two leaves, and remove those twoleaves. Call the resulting tree T’. Tree T’ is full and has n−1 internal nodes,so by the Induction Hypothesis E = I + 2(n − 1).Call the depth of node x as d. Restore the two children of x, each at leveld+1. We have nowadded d to I since x is now once again an internal node.We have now added 2(d + 1) − d = d + 2 to E since we added the two leafnodes, but lost the contribution of x to E. Thus, if before the addition we had E = I + 2(n − 1) (by the induction hypothesis), then after the addition we have E + d = I + d + 2 + 2(n − 1) or E = I + 2n which is correct. Thus,by the principle of mathematical induction, the theorem is correct.5.4 (a) template <class Elem>void inorder(BinNode<Elem>* subroot) {if (subroot == NULL) return; // Empty, do nothingpreorder(subroot->left());visit(subroot); // Perform desired actionpreorder(subroot->right());}(b) template <class Elem>void postorder(BinNode<Elem>* subroot) {if (subroot == NULL) return; // Empty, do nothingpreorder(subroot->left());preorder(subroot->right());visit(subroot); // Perform desired action}5.5 The key is to search both subtrees, as necessary.template <class Key, class Elem, class KEComp>bool search(BinNode<Elem>* subroot, Key K);if (subroot == NULL) return false;if (subroot->value() == K) return true;if (search(subroot->right())) return true;return search(subroot->left());}34 Chap. 5 Binary Trees5.6 The key is to use a queue to store subtrees to be processed.template <class Elem>void level(BinNode<Elem>* subroot) {AQueue<BinNode<Elem>*> Q;Q.enqueue(subroot);while(!Q.isEmpty()) {BinNode<Elem>* temp;Q.dequeue(temp);if(temp != NULL) {Print(temp);Q.enqueue(temp->left());Q.enqueue(temp->right());}}}5.7 template <class Elem>int height(BinNode<Elem>* subroot) {if (subroot == NULL) return 0; // Empty subtreereturn 1 + max(height(subroot->left()),height(subroot->right()));}5.8 template <class Elem>int count(BinNode<Elem>* subroot) {if (subroot == NULL) return 0; // Empty subtreeif (subroot->isLeaf()) return 1; // A leafreturn 1 + count(subroot->left()) +count(subroot->right());}5.9 (a) Since every node stores 4 bytes of data and 12 bytes of pointers, the overhead fraction is 12/16 = 75%.(b) Since every node stores 16 bytes of data and 8 bytes of pointers, the overhead fraction is 8/24 ≈ 33%.(c) Leaf nodes store 8 bytes of data and 4 bytes of pointers; internal nodesstore 8 bytes of data and 12 bytes of pointers. Since the nodes havedifferent sizes, the total space needed for internal nodes is not the sameas for leaf nodes. Students must be careful to do the calculation correctly,taking the weighting into account. The correct formula looks asfollows, given that there are x internal nodes and x leaf nodes.4x + 12x12x + 20x= 16/32 = 50%.(d) Leaf nodes store 4 bytes of data; internal nodes store 4 bytes of pointers. The formula looks as follows, given that there are x internal nodes and35x leaf nodes:4x4x + 4x= 4/8 = 50%.5.10 If equal valued nodes were allowed to appear in either subtree, then during a search for all nodes of a given value, whenever we encounter a node of that value the search would be required to search in both directions.5.11 This tree is identical to the tree of Figure 5.20(a), except that a node with value 5 will be added as the right child of the node with value 2.5.12 This tree is identical to the tree of Figure 5.20(b), except that the value 24 replaces the value 7, and the leaf node that originally contained 24 is removed from the tree.5.13 template <class Key, class Elem, class KEComp>int smallcount(BinNode<Elem>* root, Key K);if (root == NULL) return 0;if (KEComp.gt(root->value(), K))return smallcount(root->leftchild(), K);elsereturn smallcount(root->leftchild(), K) +smallcount(root->rightchild(), K) + 1;5.14 template <class Key, class Elem, class KEComp>void printRange(BinNode<Elem>* root, int low,int high) {if (root == NULL) return;if (KEComp.lt(high, root->val()) // all to leftprintRange(root->left(), low, high);else if (KEComp.gt(low, root->val())) // all to rightprintRange(root->right(), low, high);else { // Must process both childrenprintRange(root->left(), low, high);PRINT(root->value());printRange(root->right(), low, high);}}5.15 The minimum number of elements is contained in the heap with a single node at depth h − 1, for a total of 2h−1 nodes.The maximum number of elements is contained in the heap that has completely filled up level h − 1, for a total of 2h − 1 nodes.5.16 The largest element could be at any leaf node.5.17 The corresponding array will be in the following order (equivalent to level order for the heap):12 9 10 5 4 1 8 7 3 236 Chap. 5 Binary Trees5.18 (a) The array will take on the following order:6 5 3 4 2 1The value 7 will be at the end of the array.(b) The array will take on the following order:7 4 6 3 2 1The value 5 will be at the end of the array.5.19 // Min-heap classtemplate <class Elem, class Comp> class minheap {private:Elem* Heap; // Pointer to the heap arrayint size; // Maximum size of the heapint n; // # of elements now in the heapvoid siftdown(int); // Put element in correct placepublic:minheap(Elem* h, int num, int max) // Constructor{ Heap = h; n = num; size = max; buildHeap(); }int heapsize() const // Return current size{ return n; }bool isLeaf(int pos) const // TRUE if pos a leaf{ return (pos >= n/2) && (pos < n); }int leftchild(int pos) const{ return 2*pos + 1; } // Return leftchild posint rightchild(int pos) const{ return 2*pos + 2; } // Return rightchild posint parent(int pos) const // Return parent position { return (pos-1)/2; }bool insert(const Elem&); // Insert value into heap bool removemin(Elem&); // Remove maximum value bool remove(int, Elem&); // Remove from given pos void buildHeap() // Heapify contents{ for (int i=n/2-1; i>=0; i--) siftdown(i); }};template <class Elem, class Comp>void minheap<Elem, Comp>::siftdown(int pos) { while (!isLeaf(pos)) { // Stop if pos is a leafint j = leftchild(pos); int rc = rightchild(pos);if ((rc < n) && Comp::gt(Heap[j], Heap[rc]))j = rc; // Set j to lesser child’s valueif (!Comp::gt(Heap[pos], Heap[j])) return; // Done37swap(Heap, pos, j);pos = j; // Move down}}template <class Elem, class Comp>bool minheap<Elem, Comp>::insert(const Elem& val) { if (n >= size) return false; // Heap is fullint curr = n++;Heap[curr] = val; // Start at end of heap// Now sift up until curr’s parent < currwhile ((curr!=0) &&(Comp::lt(Heap[curr], Heap[parent(curr)]))) {swap(Heap, curr, parent(curr));curr = parent(curr);}return true;}template <class Elem, class Comp>bool minheap<Elem, Comp>::removemin(Elem& it) { if (n == 0) return false; // Heap is emptyswap(Heap, 0, --n); // Swap max with last valueif (n != 0) siftdown(0); // Siftdown new root valit = Heap[n]; // Return deleted valuereturn true;}38 Chap. 5 Binary Trees// Remove value at specified positiontemplate <class Elem, class Comp>bool minheap<Elem, Comp>::remove(int pos, Elem& it) {if ((pos < 0) || (pos >= n)) return false; // Bad posswap(Heap, pos, --n); // Swap with last valuewhile ((pos != 0) &&(Comp::lt(Heap[pos], Heap[parent(pos)])))swap(Heap, pos, parent(pos)); // Push up if largesiftdown(pos); // Push down if small keyit = Heap[n];return true;}5.20 Note that this summation is similar to Equation 2.5. To solve the summation requires the shifting technique from Chapter 14, so this problem may be too advanced for many students at this time. Note that 2f(n) − f(n) = f(n),but also that:2f(n) − f(n) = n(24+48+616+ ··· +2(log n − 1)n) −n(14+28+316+ ··· +log n − 1n)logn−1i=112i− log n − 1n)= n(1 − 1n− log n − 1n)= n − log n.5.21 Here are the final codes, rather than a picture.l 00h 010i 011e 1000f 1001j 101d 11000a 1100100b 1100101c 110011g 1101k 11139The average code length is 3.234455.22 The set of sixteen characters with equal weight will create a Huffman coding tree that is complete with 16 leaf nodes all at depth 4. Thus, the average code length will be 4 bits. This is identical to the fixed length code. Thus, in this situation, the Huffman coding tree saves no space (and costs no space).5.23 (a) By the prefix property, there can be no character with codes 0, 00, or 001x where “x” stands for any binary string.(b) There must be at least one code with each form 1x, 01x, 000x where“x” could be any binary string (including the empty string).5.24 (a) Q and Z are at level 5, so any string of length n containing only Q’s and Z’s requires 5n bits.(b) O and E are at level 2, so any string of length n containing only O’s and E’s requires 2n bits.(c) The weighted average is5 ∗ 5 + 10 ∗ 4 + 35 ∗ 3 + 50 ∗ 2100bits per character5.25 This is a straightforward modification.// Build a Huffman tree from minheap h1template <class Elem>HuffTree<Elem>*buildHuff(minheap<HuffTree<Elem>*,HHCompare<Elem> >* hl) {HuffTree<Elem> *temp1, *temp2, *temp3;while(h1->heapsize() > 1) { // While at least 2 itemshl->removemin(temp1); // Pull first two treeshl->removemin(temp2); // off the heaptemp3 = new HuffTree<Elem>(temp1, temp2);hl->insert(temp3); // Put the new tree back on listdelete temp1; // Must delete the remnantsdelete temp2; // of the trees we created}return temp3;}6General Trees6.1 The following algorithm is linear on the size of the two trees. // Return TRUE iff t1 and t2 are roots of identical// general treestemplate <class Elem>bool Compare(GTNode<Elem>* t1, GTNode<Elem>* t2) { GTNode<Elem> *c1, *c2;if (((t1 == NULL) && (t2 != NULL)) ||((t2 == NULL) && (t1 != NULL)))return false;if ((t1 == NULL) && (t2 == NULL)) return true;if (t1->val() != t2->val()) return false;c1 = t1->leftmost_child();c2 = t2->leftmost_child();while(!((c1 == NULL) && (c2 == NULL))) {if (!Compare(c1, c2)) return false;if (c1 != NULL) c1 = c1->right_sibling();if (c2 != NULL) c2 = c2->right_sibling();}}6.2 The following algorithm is Θ(n2).// Return true iff t1 and t2 are roots of identical// binary treestemplate <class Elem>bool Compare2(BinNode<Elem>* t1, BinNode<Elem* t2) { BinNode<Elem> *c1, *c2;if (((t1 == NULL) && (t2 != NULL)) ||((t2 == NULL) && (t1 != NULL)))return false;if ((t1 == NULL) && (t2 == NULL)) return true;4041if (t1->val() != t2->val()) return false;if (Compare2(t1->leftchild(), t2->leftchild())if (Compare2(t1->rightchild(), t2->rightchild())return true;if (Compare2(t1->leftchild(), t2->rightchild())if (Compare2(t1->rightchild(), t2->leftchild))return true;return false;}6.3 template <class Elem> // Print, postorder traversalvoid postprint(GTNode<Elem>* subroot) {for (GTNode<Elem>* temp = subroot->leftmost_child();temp != NULL; temp = temp->right_sibling())postprint(temp);if (subroot->isLeaf()) cout << "Leaf: ";else cout << "Internal: ";cout << subroot->value() << "\n";}6.4 template <class Elem> // Count the number of nodesint gencount(GTNode<Elem>* subroot) {if (subroot == NULL) return 0int count = 1;GTNode<Elem>* temp = rt->leftmost_child();while (temp != NULL) {count += gencount(temp);temp = temp->right_sibling();}return count;}6.5 The Weighted Union Rule requires that when two parent-pointer trees are merged, the smaller one’s root becomes a child of the larger one’s root. Thus, we need to keep track of the number of nodes in a tree. To do so, modify the node array to store an integer value with each node. Initially, each node isin its own tree, so the weights for each node begin as 1. Whenever we wishto merge two trees, check the weights of the roots to determine which has more nodes. Then, add to the weight of the final root the weight of the new subtree.6.60 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15-1 0 0 0 0 0 0 6 0 0 0 9 0 0 12 06.7 The resulting tree should have the following structure:42 Chap. 6 General TreesNode 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15Parent 4 4 4 4 -1 4 4 0 0 4 9 9 9 12 9 -16.8 For eight nodes labeled 0 through 7, use the following series of equivalences: (0, 1) (2, 3) (4, 5) (6, 7) (4 6) (0, 2) (4 0)This requires checking fourteen parent pointers (two for each equivalence),but none are actually followed since these are all roots. It is possible todouble the number of parent pointers checked by choosing direct children ofroots in each case.6.9 For the “lists of Children” representation, every node stores a data value and a pointer to its list of children. Further, every child (every node except the root)has a record associated with it containing an index and a pointer. Indicatingthe size of the data value as D, the size of a pointer as P and the size of anindex as I, the overhead fraction is3P + ID + 3P + I.For the “Left Child/Right Sibling” representation, every node stores three pointers and a data value, for an overhead fraction of3PD + 3P.The first linked representation of Section 6.3.3 stores with each node a datavalue and a size field (denoted by S). Each child (every node except the root)also has a pointer pointing to it. The overhead fraction is thusS + PD + S + Pmaking it quite efficient.The second linked representation of Section 6.3.3 stores with each node adata value and a pointer to the list of children. Each child (every node exceptthe root) has two additional pointers associated with it to indicate its placeon the parent’s linked list. Thus, the overhead fraction is3PD + 3P.6.10 template <class Elem>BinNode<Elem>* convert(GTNode<Elem>* genroot) {if (genroot == NULL) return NULL;43GTNode<Elem>* gtemp = genroot->leftmost_child();btemp = new BinNode(genroot->val(), convert(gtemp),convert(genroot->right_sibling()));}6.11 • Parent(r) = (r − 1)/k if 0 < r < n.• Ith child(r) = kr + I if kr +I < n.• Left sibling(r) = r − 1 if r mod k = 1 0 < r < n.• Right sibling(r) = r + 1 if r mod k = 0 and r + 1 < n.6.12 (a) The overhead fraction is4(k + 1)4 + 4(k + 1).(b) The overhead fraction is4k16 + 4k.(c) The overhead fraction is4(k + 2)16 + 4(k + 2).(d) The overhead fraction is2k2k + 4.6.13 Base Case: The number of leaves in a non-empty tree of 0 internal nodes is (K − 1)0 + 1 = 1. Thus, the theorem is correct in the base case.Induction Hypothesis: Assume that the theorem is correct for any full Karytree containing n internal nodes.Induction Step: Add K children to an arbitrary leaf node of the tree withn internal nodes. This new tree now has 1 more internal node, and K − 1more leaf nodes, so theorem still holds. Thus, the theorem is correct, by the principle of Mathematical Induction.6.14 (a) CA/BG///FEDD///H/I//(b) CA/BG/FED/H/I6.15 X|P-----| | |C Q R---| |V M44 Chap. 6 General Trees6.16 (a) // Use a helper function with a pass-by-reference// variable to indicate current position in the// node list.template <class Elem>BinNode<Elem>* convert(char* inlist) {int curr = 0;return converthelp(inlist, curr);}// As converthelp processes the node list, curr is// incremented appropriately.template <class Elem>BinNode<Elem>* converthelp(char* inlist,int& curr) {if (inlist[curr] == ’/’) {curr++;return NULL;}BinNode<Elem>* temp = new BinNode(inlist[curr++], NULL, NULL);temp->left = converthelp(inlist, curr);temp->right = converthelp(inlist, curr);return temp;}(b) // Use a helper function with a pass-by-reference // variable to indicate current position in the// node list.template <class Elem>BinNode<Elem>* convert(char* inlist) {int curr = 0;return converthelp(inlist, curr);}// As converthelp processes the node list, curr is// incremented appropriately.template <class Elem>BinNode<Elem>* converthelp(char* inlist,int& curr) {if (inlist[curr] == ’/’) {curr++;return NULL;}BinNode<Elem>* temp =new BinNode<Elem>(inlist[curr++], NULL, NULL);if (inlist[curr] == ’\’’) return temp;45curr++ // Eat the internal node mark.temp->left = converthelp(inlist, curr);temp->right = converthelp(inlist, curr);return temp;}(c) // Use a helper function with a pass-by-reference// variable to indicate current position in the// node list.template <class Elem>GTNode<Elem>* convert(char* inlist) {int curr = 0;return converthelp(inlist, curr);}// As converthelp processes the node list, curr is// incremented appropriately.template <class Elem>GTNode<Elem>* converthelp(char* inlist,int& curr) {if (inlist[curr] == ’)’) {curr++;return NULL;}GTNode<Elem>* temp =new GTNode<Elem>(inlist[curr++]);if (curr == ’)’) {temp->insert_first(NULL);return temp;}temp->insert_first(converthelp(inlist, curr));while (curr != ’)’)temp->insert_next(converthelp(inlist, curr));curr++;return temp;}6.17 The Huffman tree is a full binary tree. To decode, we do not need to know the weights of nodes, only the letter values stored in the leaf nodes. Thus, we can use a coding much like that of Equation 6.2, storing only a bit mark for internal nodes, and a bit mark and letter value for leaf nodes.7Internal Sorting7.1 Base Case: For the list of one element, the double loop is not executed and the list is not processed. Thus, the list of one element remains unaltered and is sorted.Induction Hypothesis: Assume that the list of n elements is sorted correctlyby Insertion Sort.Induction Step: The list of n + 1 elements is processed by first sorting thetop n elements. By the induction hypothesis, this is done correctly. The final pass of the outer for loop will process the last element (call it X). This isdone by the inner for loop, which moves X up the list until a value smallerthan that of X is encountered. At this point, X has been properly insertedinto the sorted list, leaving the entire collection of n + 1 elements correctly sorted. Thus, by the principle of Mathematical Induction, the theorem is correct.7.2 void StackSort(AStack<int>& IN) {AStack<int> Temp1, Temp2;while (!IN.isEmpty()) // Transfer to another stackTemp1.push(IN.pop());IN.push(Temp1.pop()); // Put back one elementwhile (!Temp1.isEmpty()) { // Process rest of elemswhile (IN.top() > Temp1.top()) // Find elem’s placeTemp2.push(IN.pop());IN.push(Temp1.pop()); // Put the element inwhile (!Temp2.isEmpty()) // Put the rest backIN.push(Temp2.pop());}}46477.3 The revised algorithm will work correctly, and its asymptotic complexity will remain Θ(n2). However, it will do about twice as many comparisons, since it will compare adjacent elements within the portion of the list already knownto be sorted. These additional comparisons are unproductive.7.4 While binary search will find the proper place to locate the next element, it will still be necessary to move the intervening elements down one position in the array. This requires the same number of operations as a sequential search. However, it does reduce the number of element/element comparisons, and may be somewhat faster by a constant factor since shifting several elements may be more efficient than an equal number of swap operations.7.5 (a) template <class Elem, class Comp>void selsort(Elem A[], int n) { // Selection Sortfor (int i=0; i<n-1; i++) { // Select i’th recordint lowindex = i; // Remember its indexfor (int j=n-1; j>i; j--) // Find least valueif (Comp::lt(A[j], A[lowindex]))lowindex = j; // Put it in placeif (i != lowindex) // Add check for exerciseswap(A, i, lowindex);}}(b) There is unlikely to be much improvement; more likely the algorithmwill slow down. This is because the time spent checking (n times) isunlikely to save enough swaps to make up.(c) Try it and see!7.6 • Insertion Sort is stable. A swap is done only if the lower element’svalue is LESS.• Bubble Sort is stable. A swap is done only if the lower element’s valueis LESS.• Selection Sort is NOT stable. The new low value is set only if it isactually less than the previous one, but the direction of the search isfrom the bottom of the array. The algorithm will be stable if “less than”in the check becomes “less than or equal to” for selecting the low key position.• Shell Sort is NOT stable. The sublist sorts are done independently, andit is quite possible to swap an element in one sublist ahead of its equalvalue in another sublist. Once they are in the same sublist, they willretain this (incorrect) relationship.• Quick-sort is NOT stable. After selecting the pivot, it is swapped withthe last element. This action can easily put equal records out of place.48 Chap. 7 Internal Sorting• Conceptually (in particular, the linked list version) Mergesort is stable.The array implementations are NOT stable, since, given that the sublistsare stable, the merge operation will pick the element from the lower listbefore the upper list if they are equal. This is easily modified to replace“less than” with “less than or equal to.”• Heapsort is NOT stable. Elements in separate sides of the heap are processed independently, and could easily become out of relative order.• Binsort is stable. Equal values that come later are appended to the list.• Radix Sort is stable. While the processing is from bottom to top, thebins are also filled from bottom to top, preserving relative order.7.7 In the worst case, the stack can store n records. This can be cut to log n in the worst case by putting the larger partition on FIRST, followed by the smaller. Thus, the smaller will be processed first, cutting the size of the next stacked partition by at least half.7.8 Here is how I derived a permutation that will give the desired (worst-case) behavior:a b c 0 d e f g First, put 0 in pivot index (0+7/2),assign labels to the other positionsa b c g d e f 0 First swap0 b c g d e f a End of first partition pass0 b c g 1 e f a Set d = 1, it is in pivot index (1+7/2)0 b c g a e f 1 First swap0 1 c g a e f b End of partition pass0 1 c g 2 e f b Set a = 2, it is in pivot index (2+7/2)0 1 c g b e f 2 First swap0 1 2 g b e f c End of partition pass0 1 2 g b 3 f c Set e = 3, it is in pivot index (3+7/2)0 1 2 g b c f 3 First swap0 1 2 3 b c f g End of partition pass0 1 2 3 b 4 f g Set c = 4, it is in pivot index (4+7/2)0 1 2 3 b g f 4 First swap0 1 2 3 4 g f b End of partition pass0 1 2 3 4 g 5 b Set f = 5, it is in pivot index (5+7/2)0 1 2 3 4 g b 5 First swap0 1 2 3 4 5 b g End of partition pass0 1 2 3 4 5 6 g Set b = 6, it is in pivot index (6+7/2)0 1 2 3 4 5 g 6 First swap0 1 2 3 4 5 6 g End of parition pass0 1 2 3 4 5 6 7 Set g = 7.Plugging the variable assignments into the original permutation yields:492 6 4 0 13 5 77.9 (a) Each call to qsort costs Θ(i log i). Thus, the total cost isni=1i log i = Θ(n2 log n).(b) Each call to qsort costs Θ(n log n) for length(L) = n, so the totalcost is Θ(n2 log n).7.10 All that we need to do is redefine the comparison test to use strcmp. The quicksort algorithm itself need not change. This is the advantage of paramerizing the comparator.7.11 For n = 1000, n2 = 1, 000, 000, n1.5 = 1000 ∗√1000 ≈ 32, 000, andn log n ≈ 10, 000. So, the constant factor for Shellsort can be anything less than about 32 times that of Insertion Sort for Shellsort to be faster. The constant factor for Shellsort can be anything less than about 100 times thatof Insertion Sort for Quicksort to be faster.7.12 (a) The worst case occurs when all of the sublists are of size 1, except for one list of size i − k + 1. If this happens on each call to SPLITk, thenthe total cost of the algorithm will be Θ(n2).(b) In the average case, the lists are split into k sublists of roughly equal length. Thus, the total cost is Θ(n logk n).7.13 (This question comes from Rawlins.) Assume that all nuts and all bolts havea partner. We use two arrays N[1..n] and B[1..n] to represent nuts and bolts. Algorithm 1Using merge-sort to solve this problem.First, split the input into n/2 sub-lists such that each sub-list contains twonuts and two bolts. Then sort each sub-lists. We could well come up with apair of nuts that are both smaller than either of a pair of bolts. In that case,all you can know is something like:N1, N2。
数据结构与算法分析c语言描述中文答案
数据结构与算法分析c语言描述中文答案一、引言数据结构与算法是计算机科学中非常重要的基础知识,它们为解决实际问题提供了有效的工具和方法。
本文将以C语言描述中文的方式,介绍数据结构与算法分析的基本概念和原理。
二、数据结构1. 数组数组是在内存中连续存储相同类型的数据元素的集合。
在C语言中,可以通过定义数组类型、声明数组变量以及对数组进行操作来实现。
2. 链表链表是一种动态数据结构,它由一系列的节点组成,每个节点包含了数据和一个指向下一个节点的指针。
链表可以是单链表、双链表或循环链表等多种形式。
3. 栈栈是一种遵循“先进后出”(Last-In-First-Out,LIFO)原则的数据结构。
在C语言中,可以通过数组或链表实现栈,同时实现入栈和出栈操作。
4. 队列队列是一种遵循“先进先出”(First-In-First-Out,FIFO)原则的数据结构。
在C语言中,可以通过数组或链表实现队列,同时实现入队和出队操作。
5. 树树是一种非线性的数据结构,它由节点和边组成。
每个节点可以有多个子节点,其中一个节点被称为根节点。
在C语言中,可以通过定义结构体和指针的方式来实现树的表示和操作。
6. 图图是由顶点和边组成的数据结构,它可以用来表示各种实际问题,如社交网络、路网等。
在C语言中,可以通过邻接矩阵或邻接表的方式来表示图,并实现图的遍历和查找等操作。
三、算法分析1. 时间复杂度时间复杂度是用来衡量算法的执行时间随着问题规模增长的趋势。
常见的时间复杂度有O(1)、O(log n)、O(n)、O(n^2)等,其中O表示“量级”。
2. 空间复杂度空间复杂度是用来衡量算法的执行所需的额外内存空间随着问题规模增长的趋势。
常见的空间复杂度有O(1)、O(n)等。
3. 排序算法排序算法是对一组数据按照特定规则进行排序的算法。
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序等,它们的时间复杂度和空间复杂度各不相同。
清华大学出版社数据结构(C 版)(第2版)课后习题答案最全整理
第1 章绪论课后习题讲解1. 填空⑴()是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
【解答】数据元素⑵()是数据的最小单位,()是讨论数据结构时涉及的最小数据单位。
【解答】数据项,数据元素【分析】数据结构指的是数据元素以及数据元素之间的关系。
⑶从逻辑关系上讲,数据结构主要分为()、()、()和()。
【解答】集合,线性结构,树结构,图结构⑷数据的存储结构主要有()和()两种基本方法,不论哪种存储结构,都要存储两方面的内容:()和()。
【解答】顺序存储结构,链接存储结构,数据元素,数据元素之间的关系⑸算法具有五个特性,分别是()、()、()、()、()。
【解答】有零个或多个输入,有一个或多个输出,有穷性,确定性,可行性⑹算法的描述方法通常有()、()、()和()四种,其中,()被称为算法语言。
【解答】自然语言,程序设计语言,流程图,伪代码,伪代码⑺在一般情况下,一个算法的时间复杂度是()的函数。
【解答】问题规模⑻设待处理问题的规模为n,若一个算法的时间复杂度为一个常数,则表示成数量级的形式为(),若为n*log25n,则表示成数量级的形式为()。
【解答】Ο(1),Ο(nlog2n)【分析】用大O记号表示算法的时间复杂度,需要将低次幂去掉,将最高次幂的系数去掉。
2. 选择题⑴顺序存储结构中数据元素之间的逻辑关系是由()表示的,链接存储结构中的数据元素之间的逻辑关系是由()表示的。
A 线性结构B 非线性结构C 存储位置D 指针【解答】C,D【分析】顺序存储结构就是用一维数组存储数据结构中的数据元素,其逻辑关系由存储位置(即元素在数组中的下标)表示;链接存储结构中一个数据元素对应链表中的一个结点,元素之间的逻辑关系由结点中的指针表示。
⑵假设有如下遗产继承规则:丈夫和妻子可以相互继承遗产;子女可以继承父亲或母亲的遗产;子女间不能相互继承。
则表示该遗产继承关系的最合适的数据结构应该是()。
数据结构课后习题答案详解(C语言版_严蔚敏) 2
数据结构习题集答案(C语言版严蔚敏)第2章线性表2.1 描述以下三个概念的区别:头指针,头结点,首元结点(第一个元素结点)。
解:头指针是指向链表中第一个结点的指针。
首元结点是指链表中存储第一个数据元素的结点。
头结点是在首元结点之前附设的一个结点,该结点不存储数据元素,其指针域指向首元结点,其作用主要是为了方便对链表的操作。
它可以对空表、非空表以及首元结点的操作进行统一处理。
2.2 填空题。
解:(1) 在顺序表中插入或删除一个元素,需要平均移动表中一半元素,具体移动的元素个数与元素在表中的位置有关。
(2) 顺序表中逻辑上相邻的元素的物理位置必定紧邻。
单链表中逻辑上相邻的元素的物理位置不一定紧邻。
(3) 在单链表中,除了首元结点外,任一结点的存储位置由其前驱结点的链域的值指示。
(4) 在单链表中设置头结点的作用是插入和删除首元结点时不用进行特殊处理。
2.3 在什么情况下用顺序表比链表好?解:当线性表的数据元素在物理位置上是连续存储的时候,用顺序表比用链表好,其特点是可以进行随机存取。
2.4 对以下单链表分别执行下列各程序段,并画出结果示意图。
解:2.5 画出执行下列各行语句后各指针及链表的示意图。
L=(LinkList)malloc(sizeof(LNode)); P=L;for(i=1;i<=4;i++){P->next=(LinkList)malloc(sizeof(LNode));P=P->next; P->data=i*2-1;}P->next=NULL;for(i=4;i>=1;i--) Ins_LinkList(L,i+1,i*2);for(i=1;i<=3;i++) Del_LinkList(L,i);解:2.6 已知L是无表头结点的单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的答案中选择合适的语句序列。
a. 在P结点后插入S结点的语句序列是__________________。
数据结构C语言版部分习题及答案[2]
第二章习题与解答一判断题1.线性表的逻辑顺序与存储顺序总是一致的。
2.顺序存储的线性表可以按序号随机存取。
3.顺序表的插入和删除操作不需要付出很大的时间代价,因为每次操作平均只有近一半的元素需要移动。
4.线性表中的元素可以是各种各样的,但同一线性表中的数据元素具有相同的特性,因此是属于同一数据对象。
5.在线性表的顺序存储结构中,逻辑上相邻的两个元素在物理位置上并不一定紧邻。
6.在线性表的链式存储结构中,逻辑上相邻的元素在物理位置上不一定相邻。
7.线性表的链式存储结构优于顺序存储结构。
8.在线性表的顺序存储结构中,插入和删除时,移动元素的个数与该元素的位置有关。
9.线性表的链式存储结构是用一组任意的存储单元来存储线性表中数据元素的。
10.在单链表中,要取得某个元素,只要知道该元素的指针即可,因此,单链表是随机存取的存储结构。
二单选题 (请从下列A,B,C,D选项中选择一项)1.线性表是( ) 。
(A) 一个有限序列,可以为空;(B) 一个有限序列,不能为空;(C) 一个无限序列,可以为空;(D) 一个无序序列,不能为空。
2.对顺序存储的线性表,设其长度为n,在任何位置上插入或删除操作都是等概率的。
插入一个元素时平均要移动表中的()个元素。
(A) n/2 (B) n+1/2 (C) n -1/2 (D) n3.线性表采用链式存储时,其地址( ) 。
(A) 必须是连续的;(B) 部分地址必须是连续的;(C) 一定是不连续的;(D) 连续与否均可以。
4.用链表表示线性表的优点是()。
(A)便于随机存取(B)花费的存储空间较顺序存储少(C)便于插入和删除(D)数据元素的物理顺序与逻辑顺序相同5.某链表中最常用的操作是在最后一个元素之后插入一个元素和删除最后一个元素,则采用( )存储方式最节省运算时间。
(A)单链表(B)双链表(C)单循环链表(D)带头结点的双循环链表6.循环链表的主要优点是( )。
(A)不在需要头指针了(B)已知某个结点的位置后,能够容易找到他的直接前趋(C)在进行插入、删除运算时,能更好的保证链表不断开(D)从表中的任意结点出发都能扫描到整个链表7.下面关于线性表的叙述错误的是( )。
算法与数据结构C语言习题参考答案1-5章
绪论1.将下列复杂度由小到大重新排序:A.2n B.n! C.n5D.10 000 E.n*log2 (n)【答】10 000< n*log2(n)< n5< 2n < n!2.将下列复杂度由小到大重新排序:A.n*log2(n) B.n + n2 + n3C.24D.n0.5【答】24< n0.5< n*log2 (n) < n + n2 + n33.用大“O”表示法描述下列复杂度:A.5n5/2 + n2/5 B.6*log2(n) + 9nC.3n4+ n* log2(n) D.5n2 + n3/2【答】A:O (n5/2) B:O (n) C:O (n4) D:O (n2)4.按照增长率从低到高的顺序排列以下表达式:4n2 , log3n, 3n , 20n , 2000 , log2n , n2/3。
又n!应排在第几位?【答】按照增长率从低到高依次为:2000, log3n, log2n , n2/3 , 20n , 4n2 , 3n。
n!的增长率比它们中的每一个都要大,应排在最后一位。
5. 计算下列程序片断的时间代价:int i=1;while(i<=n){printf(“i=%d\n”,i);i=i+1;}【答】循环控制变量i从1增加到n,循环体执行n次,第一句i的初始化执行次数为1,第二句执行n次,循环体中第一句printf执行n次,第二句i从1循环到n,共执行n次。
所以该程序段总的时间代价为:T(n) = 1 + n + 2n = 3n+ 1 = O(n)6. 计算下列程序片断的时间代价:int i=1;while(i<=n){int j=1;while(j<=n){int k=1;while(k<=n){printf(“i=%d,j=%d,k=%d\n”,I,j,k);k=k+1;}j=j+1;}i=i+1;}【答】循环控制变量i从1增加到n,最外层循环体执行n次,循环控制变量j从1增加到n,中间层循环体执行n次,循环控制变量k从1增加到n,最内层循环体执行n次,所以该程序段总的时间代价为:T(n) = 1 + n + n{1 + n + n[1 + n + 2n +1] +1 +1}+ 1= 3n3 + 3n2 +4n +2= O(n3)2. 线性表1.试写一个插入算法int insertPost_seq(palist, p, x ),在palist所指顺序表中,下标为p的元素之后,插入一个值为x的元素,返回插入成功与否的标志。
《数据结构(C语言版)》课后答案 课后题答案
//输出字符串 str
DestroyStack (&S);
DestroyStack (&T);
} 5.解答: int ACK ( int m, int n) {
if ( m == 0) return n + 1;
if ( m <> 0 && n == 0 ) return ACK( m - 1, 1);
{'>', '>', '>', '>', '<', '>', '>'}, {'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', ' '}, {'>', '>', '>', '>', ' ', '>', '>'},
{'<', '<', '<', '<', '<', ' ', '='}};
}
项目三 栈和队列
算法与数据结构C语言版课后习题参考答案(机械工业出版社)1绪论习题详细答案
第1章概论习题参考答案一、基础知识题1.简述下列概念数据,数据元素,数据类型,数据结构,逻辑结构,存储结构,算法。
【解答】数据是信息的载体,是描述客观事物的数、字符,以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。
数据元素是数据的基本单位。
在不同的条件下,数据元素又可称为元素、结点、顶点、记录等。
数据类型是对数据的取值范围、数据元素之间的结构以及允许施加操作的一种总体描述。
每一种计算机程序设计语言都定义有自己的数据类型。
“数据结构”这一术语有两种含义,一是作为一门课程的名称;二是作为一个科学的概念。
作为科学概念,目前尚无公认定义,一般认为,讨论数据结构要包括三个方面,一是数据的逻辑结构,二是数据的存储结构,三是对数据进行的操作(运算)。
而数据类型是值的集合和操作的集合,可以看作是已实现了的数据结构,后者是前者的一种简化情况。
数据的逻辑结构反映数据元素之间的逻辑关系(即数据元素之间的关联方式或“邻接关系”),数据的存储结构是数据结构在计算机中的表示,包括数据元素的表示及其关系的表示。
数据的运算是对数据定义的一组操作,运算是定义在逻辑结构上的,和存储结构无关,而运算的实现则依赖于存储结构。
数据结构在计算机中的表示称为物理结构,又称存储结构。
是逻辑结构在存储器中的映像,包括数据元素的表示和关系的表示。
逻辑结构与计算机无关。
算法是对特定问题求解步骤的一种描述,是指令的有限序列。
其中每一条指令表示一个或多个操作。
一个算法应该具有下列特性:有穷性、确定性、可行性、输入和输出。
2.数据的逻辑结构分哪几种,为什么说逻辑结构是数据组织的主要方面?【解答】数据的逻辑结构分为线性结构和非线性结构。
(也可以分为集合、线性结构、树形结构和图形即网状结构)。
逻辑结构是数据组织的某种“本质性”的东西:(1)逻辑结构与数据元素本身的形式、内容无关。
(2)逻辑结构与数据元素的相对位置无关。
(3)逻辑结构与所含数据元素的个数无关。
严蔚敏数据结构(C语言版)知识点总结笔记课后答案
第1章绪论1.1复习笔记一、数据结构的定义数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科。
二、基本概念和术语数据数据(data)是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称,它是计算机程序加工的“原料”。
2.数据元素数据元素(data element)是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
3.数据对象数据对象(data object)是性质相同的数据元素的集合,是数据的一个子集。
4.数据结构数据结构(data structure)是相互之间存在一种或多种特定关系的数据元素的集合。
(1)数据结构的基本结构根据数据元素之间关系的不同特性,通常有下列四类基本结构:① 集合。
数据元素之间除了“同属于一个集合”的关系外,别无其它关系。
② 线性结构。
数据元素之间存在一个对一个的关系。
③ 树形结构。
数据元素之间存在一个对多个的关系。
④ 图状结构或网状结构。
数据元素之间存在多个对多个的关系。
如图1-1所示为上述四类基本结构的关系图。
图1-1 四类基本结构的关系图(2)数据结构的形式定义数据结构的形式定义为:数据结构是一个二元组Data_Structure==(D,S)其中:D表示数据元素的有限集,S表示D上关系的有限集。
(3)数据结构在计算机中的表示数据结构在计算机中的表示(又称映象)称为数据的物理结构,又称存储结构。
它包括数据元素的表示和关系的表示。
① 元素的表示。
计算机数据元素用一个由若干位组合起来形成的一个位串表示。
② 关系的表示。
计算机中数据元素之间的关系有两种不同的表示方法:顺序映象和非顺序映象。
并由这两种不同的表示方法得到两种不同的存储结构:顺序存储结构和链式存储结构。
a.顺序映象的特点是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。
b.非顺序映象的特点是借助指示元素存储地址的指针(pointer)表示数据元素之间的逻辑关系。
算法与数据结构C语言版课后习题答案(机械工业出版社)第3,4章习题参考答案
算法与数据结构C语⾔版课后习题答案(机械⼯业出版社)第3,4章习题参考答案第3章栈和队列⼀、基础知识题3.1有五个数依次进栈:1,2,3,4,5。
在各种出栈的序列中,以3,4先出的序列有哪⼏个。
(3在4之前出栈)。
【解答】34215 ,34251,345213.2铁路进⾏列车调度时,常把站台设计成栈式结构,若进站的六辆列车顺序为:1,2,3,4,5,6,那么是否能够得到435612, 325641, 154623和135426的出站序列,如果不能,说明为什么不能;如果能,说明如何得到(即写出"进栈"或"出栈"的序列)。
【解答】输⼊序列为123456,不能得出435612和154623。
不能得到435612的理由是,输出序列最后两元素是12,前⾯4个元素(4356)得到后,栈中元素剩12,且2在栈顶,不可能让栈底元素1在栈顶元素2之前出栈。
不能得到154623的理由类似,当栈中元素只剩23,且3在栈顶,2不可能先于3出栈。
得到325641的过程如下:1 2 3顺序⼊栈,32出栈,得到部分输出序列32;然后45⼊栈,5出栈,部分输出序列变为325;接着6⼊栈并退栈,部分输出序列变为3256;最后41退栈,得最终结果325641。
得到135426的过程如下:1⼊栈并出栈,得到部分输出序列1;然后2和3⼊栈,3出栈,部分输出序列变为13;接着4和5⼊栈,5,4和2依次出栈,部分输出序列变为13542;最后6⼊栈并退栈,得最终结果135426。
3.3若⽤⼀个⼤⼩为6的数组来实现循环队列,且当前rear和front的值分别为0和3,当从队列中删除⼀个元素,再加⼊两个元素后,rear和front的值分别为多少?【解答】2和43.4设栈S和队列Q的初始状态为空,元素e1,e2,e3,e4,e5和e6依次通过栈S,⼀个元素出栈后即进队列Q,若6个元素出队的序列是e3,e5,e4,e6,e2,e1,则栈S的容量⾄少应该是多少?【解答】43.5循环队列的优点是什么,如何判断“空”和“满”。
数据结构与算法分析c第三版答案
数据结构与算法分析c第三版答案【篇一:数据结构第三章习题答案】txt>#include iostream#include stringusing namespace std;bool huiwen(string s){int n=s.length();int i,j;i= 0;j=n-1;while(ij s[i]==s[j]){ i++;j--;}if(i=j) return true;else return false;}int main(){string s1;cins1;couthuiwen(s1);return 0;}=============(2)设从键盘输入一整数的序列:a1, a2, a3,…,an,试编写算法实现:用栈结构存储输入的整数,当ai≠-1时,将ai进栈;当ai=-1时,输出栈顶整数并出栈。
算法应对异常情况(入栈满等)给出相应的信息。
#include iostreamusing namespace std;#define overflow -2#define ok 1#define error 0typedef int selemtype;typedef int status;typedef struct{selemtype a[5];int top;} sqstack;status initstack(sqstack s){s.top=0;return ok;}status push(sqstack s,selemtype e){if (s.top4){coutoverlow!endl;return error;}else s.a[s.top++]=e;return ok;}status pop(sqstack s,selemtype e){if (s.top==0) {coutunderflowendl; return error;}e=s.a[--s.top];couteendl;return ok;}int main(){sqstack s;initstack(s);int n,x,e1;coutn=?endl;cinn;for(int i=0;in;i++){ cinx;if(x!=-1 )push(s,x);else pop(s,e1); }return 0;}============(3)假设以i和o分别表示入栈和出栈操作。
数据结构与算法分析c语言描述中文答案
数据结构与算法分析c语言描述中文答案【篇一:数据结构(c语言版)课后习题答案完整版】选择题:ccbdca6.试分析下面各程序段的时间复杂度。
(1)o(1)(2)o(m*n)(3)o(n2)(4)o(log3n)(5)因为x++共执行了n-1+n-2+??+1= n(n-1)/2,所以执行时间为o(n2)(6)o(n)第2章线性表1.选择题babadbcabdcddac 2.算法设计题(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
elemtype max (linklist l ){if(l-next==null) return null;pmax=l-next; //假定第一个结点中数据具有最大值 p=l-next-next; while(p != null ){//如果下一个结点存在if(p-data pmax-data) pmax=p;p=p-next; }return pmax-data;(7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
void inverse(linklist l) { // 逆置带头结点的单链表 l p=l-next; l-next=null; while ( p) {q=p-next; // q指向*p的后继p-next=l-next;l-next=p; // *p插入在头结点之后p = q; }}(10)已知长度为n的线性表a采用顺序存储结构,请写一时间复杂度为o(n)、空间复杂度为o(1)的算法,该算法删除线性表中所有值为item的数据元素。
[题目分析] 在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动(删第i个元素,第i+1至第n个元素要依次前移)。
本题要求删除线性表中所有值为item的数据元素,并未要求元素间的相对位置不变。
因此可以考虑设头尾两个指针(i=1,j=n),从两端向中间移动,凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置。
算法与数据结构C语言习题参考答案6-9章
1. 现在有一个已排序的字典,请改写二分法检索算法,使之当排序码key在字典中重复出现时算法能找出第一个key出现的元素下标(用*position来保存)。
保持算法时间代价为O(log n)。
【答】思路一般的二分法检索算法只要找出关键码key在字典中的一个下标。
在比较的过程中,一旦发现相等,记录下当前下标mid就符合要求。
程序如下:数据结构字典采用6.1.4节中的顺序表示法。
typedef int KeyType;typedef int DataType;二分法检索算法int binarySearch(SeqDictionary * pdic, KeyType key, int * position) {int low, mid, high;low = 0;high = pdic->n - 1;while (low <= high){mid = (low + high) / 2;if (pdic->element[mid].key = = key) {*position = mid;return TRUE;}elseif (pdic->element[mid].key > key)high = mid - 1;elselow = mid + 1;}*position = low;return FALSE;}改写后的算法想要找出关键码key在字典中第一次出现的下标。
在比较中,如果遇到相等(key与pdic->element[mid].key相等),则需要分情形讨论。
(1)如果当前下标mid等于0,或者key与pdic->element[mid-1].key不等,那么mid 一定是key第一次出现的下标,返回mid即可。
(2)如果情形(1)不成立,那么mid一定大于等于key第一次出现的下标,需要在low 和mid-1之间继续进行搜索,找出key第一次出现的下标。
数据结构c语言版课后习题答案完整版
数据结构c语言版课后习题答案完整版Document serial number【KKGB-LBS98YT-BS8CB-BSUT-BST108】第1章绪论5.选择题:CCBDCA6.试分析下面各程序段的时间复杂度。
(1)O(1)(2)O(m*n)(3)O(n2)n)(4)O(log3(5)因为x++共执行了n-1+n-2+……+1= n(n-1)/2,所以执行时间为O(n2)(6)O(n)第2章线性表1.选择题babadbcabdcddac2.算法设计题(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
ElemType Max (LinkList L ){if(L->next==NULL) return NULL;pmax=L->next; 法设计题(2)回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。
试写一个算法判定给定的字符向量是否为回文。
(提示:将一半字符入栈)根据提示,算法可设计为:合应用题(1)已知模式串t=‘abcaabbabcab’写出用KMP法求得的每个字符对应的next和nextval函数值。
-1到9,列下标从1到11,从首地址S开始连续存放主存储器中,主存储器字长为16位。
求:①存放该数组所需多少单元②存放数组第4列所有元素至少需多少单元③数组按行存放时,元素A[7,4]的起始地址是多少④ 数组按列存放时,元素A[4,7]的起始地址是多少每个元素32个二进制位,主存字长16位,故每个元素占2个字长,行下标可平移至1到11。
(1)242 (2)22 (3)s+182 (4)s+142(4)请将香蕉banana 用工具 H( )—Head( ),T( )—Tail( )从L 中取出。
L=(apple,(orange,(strawberry,(banana)),peach),pear)H (H (T (H (T (H (T (L )))))))(5)写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z 这26个字母和0-9这10个数字)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Data Structures and Algorithm 习题答案
Preface ii
1 Data Structures and Algorithms 1
2 Mathematical Preliminaries 5
3 Algorithm Analysis 17
4 Lists, Stacks, and Queues 23
5 Binary Trees 32
6 General Trees 40
7 Internal Sorting 46
8 File Processing and External Sorting 54 9Searching 58
10 Indexing 64
11 Graphs 69
12 Lists and Arrays Revisited 76
13 Advanced Tree Structures 82
i
ii Contents
14 Analysis Techniques 88
15 Limits to Computation 94
Preface
Contained herein are the solutions to all exercises from the textbook A Practical Introduction to Data Structures and Algorithm Analysis, 2nd edition.
For most of the problems requiring an algorithm I have given actual code. In
a few cases I have presented pseudocode. Please be aware that the code presented in this manual has not actually been compiled and tested. While I believe the algorithms
to be essentially correct, there may be errors in syntax as well as semantics. Most importantly, these solutions provide a guide to the instructor as to the intended
answer, rather than usable programs.
1
Data Structures and Algorithms
Instructor’s note: Unlike the other chapters, many of the questions in this chapter are not really suitable for graded work. The questions are mainly intended to get students thinking about data structures issues.
1.1
This question does not have a specific right answer, provided the student keeps to the spirit of the question. Students may have trouble with the concept of “operations.”
1.2
This exercise asks the student to expand on their concept of an integer representation.
A good answer is described by Project 4.5, where a singly-linked
list is suggested. The most straightforward implementation stores each digit
in its own list node, with digits stored in reverse order. Addition and multiplication
are implemented by what amounts to grade-school arithmetic. For
addition, simply march down in parallel through the two lists representing
the operands, at each digit appending to a new list the appropriate partial sum and bringing forward a carry bit as necessary. For multiplication, combine the addition function with a new function that multiplies a single digit
by an integer. Exponentiation can be done either by repeated multiplication (not really practical) or by the traditional Θ(log n)-time algorithm based on the binary representation of the exponent. Discovering this faster algorithm will be beyond the reach of most students, so should not be required.
1.3
A sample ADT for character strings might look as follows (with the normal interpretation of the function names assumed).
Chap. 1 Data Structures and Algorithms
// Concatenate two strings
String strcat(String s1, String s2);
// Return the length of a string
int length(String s1);
// Extract a substring, starting at ‘start’,
// and of length ‘length’
String extract(String s1, int start, int length);
// Get the first character
char first(String s1);
// Compare two strings: the normal C++ strcmp function.
Some
// convention should be indicated for how to interpret
the
// return value. In C++, this is 1
for s1<s2; 0 for s1=s2;
// and 1 for s1>s2.
int strcmp(String s1, String s2)
// Copy a string
int strcpy(String source, String destination)
1.4
The answer to this question is provided by the ADT for lists given in Chapter 4.
1.5
One’s compliment stores the binary representation of positive numbers, and stores the binary representation of a negative number with the bits inverted. Two’s compliment is the same, except that a negative number has its bits inverted and then one is added (for reasons of efficiency in hardware implementation).
This representation is the physical implementation of an ADT。