编程珠玑 ~~ 排序与随机整数序列
2013-07-16 15:43
281 查看
11. 排序算法
插入排序:
版本1:
版本2:
简单快速排序:
版本1:
版本2:从末尾向开始进行循环,将循环后的swap删除
附注:
版本3:本版本主要是解决快速排序在待排序数组中的元素相同元素居多时,性能急剧下降而给出的。
版本4:将swap函数展开到程序中,而不使用函数调用
补充:
2.将x[l]用作标记值来提高Lomuto的划分方法的效率,说明该方法是如何在循环之后将swap移除的。
两种方法:从u开始循环
代码详解版本2中两个方法
9.编写程序,让该程序在O(n)时间内从数组x[0..n-1]中找出第k个最小的元素,你的算法可以排列x的元素
使用快速排序中的一步排序,最终将第k大的数字排到它自己的位置上。
注:注意在程序中,第k大时,调用函数传递的应该是k-1。与写的代码有关系
12. 抽样问题
问题:给出1 – K 内的M个随机的不重复整数
解决方法:
1.使用标准库的集合容器,实现1~K内的随机的无重复M个整数。
Initializeset S to empty
size= 0
whilesize < m do
t= bigrand() % n
ift is not in S
insertt into S
size++
printthe elements of S in Sorted Orger
这个方法主要是使用了集合中不会插入重复的数字
2.产生随机整数排序子集的另外一个方法是将一个K个元素的数组打乱,这个数组中前M个元素输出,即我们要的不重复的M个整数。
fori = [0, n)
swap(i, randint( i, n-1));
其实这个只需要扰乱前M个数字即可,不需要将整个数组都打乱。
补充:
1.一般的C库中的rand()函数大概随机返回15个随机位,使用该函数实现函数bigrand(),使其返回30个随机位,并实现randint(l, u)。
9.当m接近n时,基于集合的算法会产生很多集合中早就存在的整数,因此需要去掉这些整数,你能写一个算法,即便是在最差的情况下,该算法只需要m个随机数值?
可以选择 n – m个随机数,然后让最终得到的集合中排出这几个数字即可。这样得到的大部分数据都是可用的,而不会出现题目的问题。(这是一个思维的问题)
13. 堆排序
对操作中两个关键的函数:两个函数主要用于修补在一端或另一端中断的堆属性,两个函数的效率都较高,大概是log n步来重新组织具有n个元素的堆。
Siftup:将位于n的元素沿着树向上调整到适当的位置。
Siftdown:将位于n的元素沿着树向下调整到适当的位置。
使用的swap()方法:
优先队列:
C++写的一个简单的优先级队列:
使用两个函数所形成的快速排序方法:
14. 字符串(略)
插入排序:
版本1:
#include<iostream> using namespace std; #define N 10 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; for(int i = 0; i < N;i++) { for(int j = i; j >0 && array[j -1] > array[j]; j--) { swap(array[j-1],array[j]); } } for(int i = 0; i < N;i++) { cout <<array[i]<< " "; } cout << endl; return 0; }
版本2:
#include <iostream> using namespace std; #define N 10 int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; for(int i = 0; i < N;i++) { for(int j = i; j >0 && array[j -1] > array[j]; j--) { int temp =array[j-1]; array[j-1] =array[j]; array[j] = temp; } } for(int i = 0; i < N;i++) { cout <<array[i]<< " "; } cout << endl; return 0; } 版本3: #include <iostream> using namespace std; #define N 10 int main() { int array = {3, 5, 23, 53, 44, 22, 11, 8,99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; int t = 0; int j = 0; for(int i = 0; i < N;i++) { t = array[i]; for( j = i; j > 0&& array[j -1] > t; j--) { array[j] =array[j-1]; } array[j] = t; } for(int i = 0; i < N;i++) { cout <<array[i]<< " "; } cout << endl; return 0; }
简单快速排序:
版本1:
#include <iostream> using namespace std; #define N 10 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void qsort1(int array[], int l, int u) { if( l >= u) { return ; } int m = l; for( int i = l + 1; i<= u; i++) { if(array[i] <array[l]) { swap(array[++m],array[i]); } } swap(array[l], array[m]); qsort1(array, l, m-1); qsort1(array, m+1, u); } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; qsort1(array, 0, N-1); for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; return 0; }
版本2:从末尾向开始进行循环,将循环后的swap删除
#include<iostream> using namespace std; #define N 10 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void qsort1(int array[], int l, int u) { if( l >= u) { return ; } int m = u+1; // 将x[l]作为哨兵 int t = array[l]; for( int i = u; i >= l; i--) { if(array[i] >= t) { swap(array[--m],array[i]); } } // swap(array[l],array[m]); qsort1(array, l, m-1); qsort1(array, m+1, u); } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; qsort1(array, 0, N-1); for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; return 0; }
附注:
#include<iostream> using namespace std; #define N 10 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void qsort1(int array[], int l, int u) { if( l >= u) { return ; } int m = u+1; int i = u+1; int t = array[l]; do{ while(array[--i] <t) ; swap(array[--m], array[i]); }while( i != l) qsort1(array, l, m-1); qsort1(array, m+1, u); } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; qsort1(array, 0, N-1); for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; return 0; }
版本3:本版本主要是解决快速排序在待排序数组中的元素相同元素居多时,性能急剧下降而给出的。
#include<iostream> using namespace std; #define N 10 void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void qsort3(int array[], int l, int u) { if( l >= u) { return ; } int t = array[l]; int i = l; int j = u + 1; do { do{ i++; }while( i<= u && array[i] < t); do{ j--; }while( j>= i && array[j] > t); if( i > j) { break; } swap(array[i],array[j]); }while(1); swap(array[l], array[j]); qsort3(array, l, j-1); qsort3(array, j+1, u); } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; qsort3(array, 0, N-1); for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; return 0; }
版本4:将swap函数展开到程序中,而不使用函数调用
#include<iostream> using namespace std; #define N 10 void qsort3(int array[], int l, int u) { if( l >= u) { return ; } int t = array[l]; int i = l; int j = u + 1; do { do{ i++; }while( i<= u && array[i] < t); do{ j--; }while( j>= i && array[j] > t); if( i > j) { break; } int temp = array[i]; array[i] = array[j]; array[j] = temp; }while(1); int temp = array[l]; array[l] = array[j]; array[j] = temp; qsort3(array, l, j-1); qsort3(array, j+1, u); } int main() { int array = {3, 5, 23,53, 44, 22, 11, 8, 99, 77}; for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; qsort3(array, 0, N-1); for(int i = 0; i < N;i++) { cout << array[i]<< " "; } cout << endl; return 0; }
补充:
2.将x[l]用作标记值来提高Lomuto的划分方法的效率,说明该方法是如何在循环之后将swap移除的。
两种方法:从u开始循环
代码详解版本2中两个方法
9.编写程序,让该程序在O(n)时间内从数组x[0..n-1]中找出第k个最小的元素,你的算法可以排列x的元素
使用快速排序中的一步排序,最终将第k大的数字排到它自己的位置上。
注:注意在程序中,第k大时,调用函数传递的应该是k-1。与写的代码有关系
#include<iostream> using namespacestd; #define N 10 void swap(int&a, int &b) { int temp = a; a = b; b = temp; } voidselectKth(int array[], int l, int u, int k) { if( l >= u) { return ; } int t = array[l]; int i = l; int j = u + 1; do { do{ i++; }while( i <= u &&array[i] < t); do{ j--; }while( j >= i &&array[j] > t); if( i > j) { break; } swap(array[i], array[j]); }while(1); swap(array[l], array[j]); if( j < k) { selectKth(array, j+1, u, k); } else if( j > k) { selectKth(array, l, j-1, k); } } int main() { int array = {3, 5, 23, 53, 44, 22, 11,8, 99, 77}; for(int i = 0; i < N; i++) { cout << array[i] << ""; } cout << endl; selectKth(array, 0, N-1, 2); cout << "The three big: "<< array[3] << endl; return 0; }
12. 抽样问题
问题:给出1 – K 内的M个随机的不重复整数
解决方法:
1.使用标准库的集合容器,实现1~K内的随机的无重复M个整数。
Initializeset S to empty
size= 0
whilesize < m do
t= bigrand() % n
ift is not in S
insertt into S
size++
printthe elements of S in Sorted Orger
这个方法主要是使用了集合中不会插入重复的数字
2.产生随机整数排序子集的另外一个方法是将一个K个元素的数组打乱,这个数组中前M个元素输出,即我们要的不重复的M个整数。
fori = [0, n)
swap(i, randint( i, n-1));
其实这个只需要扰乱前M个数字即可,不需要将整个数组都打乱。
补充:
1.一般的C库中的rand()函数大概随机返回15个随机位,使用该函数实现函数bigrand(),使其返回30个随机位,并实现randint(l, u)。
intbigrand() { return RAND_MAX * rand() + rand(); } int randint() { return l + bigrand() % ( u – l + 1); }
9.当m接近n时,基于集合的算法会产生很多集合中早就存在的整数,因此需要去掉这些整数,你能写一个算法,即便是在最差的情况下,该算法只需要m个随机数值?
可以选择 n – m个随机数,然后让最终得到的集合中排出这几个数字即可。这样得到的大部分数据都是可用的,而不会出现题目的问题。(这是一个思维的问题)
13. 堆排序
对操作中两个关键的函数:两个函数主要用于修补在一端或另一端中断的堆属性,两个函数的效率都较高,大概是log n步来重新组织具有n个元素的堆。
Siftup:将位于n的元素沿着树向上调整到适当的位置。
void Siftup( int array[], int n) { int i = n; int p = 0; while(1) { if(i == 1) { break; } p = i / 2; if(array[p] <=array[i]) { break; } swap(array[p],array[i]); i = p; } }
Siftdown:将位于n的元素沿着树向下调整到适当的位置。
void Siftdown(int array[], int n) { int i = 1; int c = 0; while(1) { c = 2 * i; if(c > n) { break; } if( c+1 <= n) { if(array[c+1] <array[c]) { c++; } } if(array[i] <=array[c]) { break; } swap(array[c],array[i]); i = c; } }
使用的swap()方法:
void swap(int &a, int &b) { int temp = a; a = b; b = temp; }
优先队列:
C++写的一个简单的优先级队列:
#include <iostream> using namespace std; template <typename T> class priqueque { public: priqueque(int m); ~priqueque(); void insert(T t); T extractmin(); private: void swap(int i, int j) { T t = x[i]; x[i] =x[j]; x[j] = t; } private: int n; int maxsize; T *x; }; template <typename T> priqueque<T>::priqueque(int m) { maxsize = m; x = new T[maxsize+1]; n = 0; } template <typename T> priqueque<T>::~priqueque() { delete [] x; } template <typename T> void priqueque<T>::insert(T t) { int i, p; x[++n] = t; for( i = n; i > 1&& x[p=i/2] > x[i]; i = p) { swap(p, i); } } template <typename T> T priqueque<T>::extractmin() { int i, c; T t = x[1]; x[1] = x[n--]; for( i = 1; (c= 2*i) <n; i = c) { if(c+1 <= n&& x[c+1] < x[c]) c++; if(x[i] <= x[c]) break; swap(c, i); } return t; } int main() { priqueque<int>intQ(10); intQ.insert(1); intQ.insert(2); intQ.insert(3); intQ.insert(4); intQ.insert(5); intQ.insert(6); intQ.insert(7); intQ.insert(8); cout <<intQ.extractmin() << endl; cout <<intQ.extractmin() << endl; cout <<intQ.extractmin() << endl; cout << intQ.extractmin()<< endl; cout <<intQ.extractmin() << endl; cout <<intQ.extractmin() << endl; cout <<intQ.extractmin() << endl; cout << "Helloworld!" << endl; return 0; }
使用两个函数所形成的快速排序方法:
#include <iostream>
using namespace std;
void swap(int &a, int &b) { int temp = a; a = b; b = temp; }
void Siftup( int array[], int n) { int i = n; int p = 0; while(1) { if(i == 1) { break; } p = i / 2; if(array[p] <=array[i]) { break; } swap(array[p],array[i]); i = p; } }
void Siftdown(int array[], int n) { int i = 1; int c = 0; while(1) { c = 2 * i; if(c > n) { break; } if( c+1 <= n) { if(array[c+1] <array[c]) { c++; } } if(array[i] <=array[c]) { break; } swap(array[c],array[i]); i = c; } }
void HeapSort( int array[], int n)
{
for( int i = 2; i <= n;i++)
{
Siftup(array, n);
}
for( int i = n; i >= 2;i--)
{
swap( array[1],array[i]);
Siftdown( array, i -1);
}
}
#define N 10
int main()
{
int array[N+1] = {0, 3, 5,23, 34, 11, 66, 89, 43, 9, 10};
for( int i = 1; i < N +1; i++)
{
cout << array[i]<< " ";
}
cout << endl;
HeapSort(array, N);
for( int i = 1; i < N +1; i++)
{
cout << array[i] << " ";
}
cout << endl;
return 0;
}
14. 字符串(略)
相关文章推荐
- 编程珠玑: 13章 搜索 13.1生成[0 ,maxval]范围内m各随机整数的有序序列 -------解题总结
- 编程珠玑: 13章 搜索 13.4使用整数结构,生成[0 ,maxval]范围内m各随机整数的有序序列 -------解题总结
- 编程珠玑之第一章习题6给每个整数不超过10次的100w数据排序的测试用例
- 编程珠玑之第一章习题3:度量100w整数排序的运行时间
- 编程珠玑: 12章 取样问题 12.1程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。 优化解法-------解题总结
- 编程珠玑_第十三章_生成一个随机整数的有序集合
- 编程珠玑: 12章 取样问题 12.3设计空间,程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。 -------解题总结
- 编程珠玑:位图排序海量整数
- 编程珠玑: 12章 取样问题 12.3设计空间,程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复。 解法2-------解题总结
- 编程珠玑之第一章习题4: 生成不同的随机顺序的随机整数及存储与读取
- 算法 - 有一个连续整数序列,里面随机存放的是0到99这100个不重复的整数,要求对该序列排序。
- 编程珠玑---读书笔记---生成随机整数的有序子集
- 编程珠玑之第二章questionA: 40亿个随机排列整数问题
- N个整数(数的大小为0-255)的序列,把它们加密为K个整数(数的大小为0-255).再将K个整数顺序随机打乱,使得可以从这乱序的K个整数中解码出原序列。设计加密解密算法,且要求K<=15*N.
- 【编程珠玑】第十四章 堆(排序,优先级队列)
- 随机产生N个整数,并对其进行排序,查找……
- 【编程珠玑-读书笔记】用位图解决排序问题--仔细分析问题的重要性
- 编程珠玑习题:数字重复出现位图排序
- [编程珠玑]-第十一章:快速排序及第k小元素
- 输入10个整数,将它们从小到大排序后输出,并给出现每个元素在原来序列中的位置。