// 基数排序 输入:存放元素的链表 L,关键字的数字位数 k 输出:按递增顺序排序的链表 L template <class Type> void radix_sort(Type* L , int k){ Type *Lhead[10] , *p ; int i , j ; for(i = 0 ; i < 10 ;i ++) Lhead[i] = new Type ; // 分配10个链表的头结点 for(i = 0 ; i < k ; i ++) { for(j = 0 ; j < 10 ; j ++) Lhead[j]->prior = Lhead[j]->next = Lhead[j] ; // 将10个链表置空 while(L->next != L){ p = del_entry(L) ; // 删去 L 的第一个元素,使 p 指向该元素 j = get_digital(p , i) ; // 从 p 所指的元素关键字取第 i 个数字 add_entry(Lhead[j] , p) ; // 把 p 所指的元素加入链表 Lhead[j] 的表尾 } for(j = 0 ; j < 10 ; j ++) append(L,Lhead[j]) ; // 将10个链表链接到 L } for(i = 0 ; i < 10 ; i ++) delete(Lhead[i]) ; // 释放10个链表的头结点 } // 取下并删除双循环链表的第一个元素 // 输入:链表的头结点指针 L 输出:被取下第一个元素的链表 L ,以及指向被取下元素的指针 template <class Type> Type* del_entry(Type *L){ Type *p ; if(p != L){ p->prior->next = p->next ; p->next->prior = p->prior ; }else p = NULL ; return p ; } // 将一个元素 插入双向循环链表的链尾 // 输入:链表的头结点指针 L 输出 , 插入元素的指针 p :插入一个元素后的链表 L template <class Type> void add_entry(Type *L , Type *p){ p->prior = L->prior ; p->next = L ; L->prior->next = p ; L->prior = p ; } // 取 p 所指向元素的关键字的第 i 为数字(最低位为第 0 位) // 输入:指向某元素的指针 p ,希望去除的关键字的第 i 位数字的位置 i 输出:该元素的关键字的第i为数字 template <class Type> int get_digital(Type *p , int i){ int key ; key = p->key ; if(i != 0) key = key / power(10 , i) ; return key % 10 ; } // 把链表 L1 的所有元素附加到链表 L 的末端 // 输入:指向链表 L1 和 L 的头结点指针 输出:附加了新内容的链表 L template <class Type> void append(Type *L , Type *L1){ if(L1->next != L1){ L->prior->next = L1->next ; L1->next->prior = L->prior ; L1->prior->next = L ; L->prior = L1->prior ; } }
习题P84 T14:初始链表的内容为:3562,6381,0356,2850,9136,3715,8329,7481,写出用基数排序算法对他们进行排序的过程。
习题 P85 T15:将基数作为参数,编写一个可以按照任意基数进行排序的算法。
template <class Type> int binarySearch(Type A[] , int low , int high , Type x){ int mid = (low + high) / 2 ; if(A[mid] == x) return mid ; else if (A[mid] > x) return binarySearch(A,mid+1 ,high,x) ; else return binarySearch(A,low,mid-1,x) ; }
typedef long long ll ; // 用分治法 求 A 的 B 次方 ll myPow(ll a , ll b){ if(b == 1) return a ; else { ll temp = myPow(a , b / 2) ; if(b % 2) return temp * temp * a ; else return temp * temp ; } } // 用分治法 求 A 的 B 次方 对 C 取余的结果 ll myPowModC(ll a , ll b , ll c){ if(b == 1) return a % c ; else { ll temp = myPowModC(a , b / 2 , c) ; if(b % 2) return temp * temp * a % c ; else return temp * temp % c ; } }
int TreeDepth(Node * root){ if(!root) return 0 ; int leftDepth = TreeDepth(root->left) ; int rightDepth = TreeDepth(root->right) ; return max(leftDepth , rightDepth) + 1 ; }
/* 在n(n>=3)枚硬币中有一枚重量不合格的硬币(重量过轻或过重),如果只有一架天平可以用来称重且称重的硬币数没有限制,设计一个算法找出这枚不合格的硬币,使得称重的次数最少?给出算法的伪码描述。如果每称1次就作为1次基本运算,分析算法最坏情况下的时间复杂度!(8分) */ // A 是 n 个的硬币的集合 int Coin(A, n) { if n 等于 1 then return 0 ; if n 等于 2 then return 1 ; k = n / 3 ; // 向下取整 将 A 中的硬币分为三部分,X , Y , Z ,且 X 和 Y 中的硬币数为 k , Z 中的硬币数为 n - 2k ; if W(X) != W(Y) { // W(X) , W(Y) 表示 X,Y 的重量 A 集合赋值为 X 和 Y 集合的并集 ; return Coin(A , 2k) + 1 ; }else{ A 集合赋值为 Z 集合 ; return Coin(A , n -2k) + 1; } } /* 最坏情况下的时间复杂度为 O(logn) 递推方程为 f(n) = f(2n/3) +O(1) ; f(1) = 0 ; f(2) = 1 ; */
// n 个互不相等的整数,按递增顺序存放于数组A,若存在一个下标 0<=i<n,使A[i]=i,设计一个O(logn)算法找到i int Search(int a[], int left , int right){ mid = (l + r) / 2; ; if(A[mid] == mid) return mid ; else if(A[mid] > mid) return Search(a , left , mid - 1) ; else return Search(a , mid + 1 , high) ; }