Data Structures and Algorithms in C++
Chapter 01 Algorithms
1-1 Why Algorithms
1-2 Introduction
Language: C++
GitHub
Path: Linear(Sort)->Tree Structures->Graph Structures
Chapter 02 Sorting Basic
2-1 Selection Sort 选择排序法
Why learn O(n^2) sorting algorithms?
· Fundamental
· Easily coding
· Useful in special conditions
· Derive intricate algorithms
· Improve intricate algorithms as based program
#include
#include
using namespace std;
void selectionSort(int arr[], int n){
for(int i = 0 ; i < n ; i ++){
// 寻找[i, n)区间里的最小值
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort(a,10);
for( int i = 0 ; i < 10 ; i ++ )
cout<
2-2 Selection Sort Using Template 使用模板(泛型)编写算法
Student.h
//宏定义解决多重引用的问题
#ifndef INC_02_SELECTION_SORT_USING_TEMPLATE_STUDENT_H
#define INC_02_SELECTION_SORT_USING_TEMPLATE_STUDENT_H
#include
#include
using namespace std;
struct Student{
string name;
int score;
//运算符<重载
bool operator<(const Student& otherStudent){
//分数相同 按首字母顺序排列
return score != otherStudent.score ?
score > otherStudent.score : name < otherStudent.name;
}
//友元函数 输出函数<<重载
friend ostream& operator<<(ostream &os, const Student &student){
os<<"Student: "<
main.cpp
#include
#include "Student.h"
using namespace std;
//模板函数声明
template
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
// 测试模板函数,传入整型数组
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort( a , 10 );
for( int i = 0 ; i < 10 ; i ++ )
cout<
2-3 Selection Sort Generate Test Cases 随机生成算法测试用例
SortTestHelper.h
#ifndef INC_03_SELECTION_SORT_GENERATE_TEST_CASES_SORTTESTHELPER_H
#define INC_03_SELECTION_SORT_GENERATE_TEST_CASES_SORTTESTHELPER_H
#include
#include
#include
#include //自己加的,没有运行不了
using namespace std;
namespace SortTestHelper {
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int *generateRandomArray(int n, int rangeL, int rangeR) {
assert(rangeL <= rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
template
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
};
#endif //INC_03_SELECTION_SORT_GENERATE_TEST_CASES_SORTTESTHELPER_H
main.cpp
#include
#include "SortTestHelper.h"
using namespace std;
template
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
// 测试排序算法辅助函数
int N = 10000;
int *arr = SortTestHelper::generateRandomArray(N,0,100000);
selectionSort(arr,N);
SortTestHelper::printArray(arr,N);
delete[] arr;
return 0;
}
2-4 Selection Sort Detect Performance 测试算法的性能
SortTestHelper.h
#ifndef INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
#define INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
#include
#include
#include
#include
#include
using namespace std;
namespace SortTestHelper {
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int *generateRandomArray(int n, int rangeL, int rangeR) {
assert(rangeL <= rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
template
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template
bool isSorted(T arr[], int n) {//Sort函数正确性
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
template
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
assert(isSorted(arr, n));
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;//Sort函数程序执行了多少秒
return;
}
};
#endif //INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
main.cpp
#include
#include "SortTestHelper.h"
using namespace std;
template
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
int n = 10000;
int *arr = SortTestHelper::generateRandomArray(n,0,n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr, n);
delete[] arr;
return 0;
}
2-5 Insertion Sort 插入排序法
整理扑克牌
SortTestHelper.h
#ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H
#define INC_04_INSERTION_SORT_SORTTESTHELPER_H
#include
#include
#include
#include
#include
using namespace std;
namespace SortTestHelper {
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (range_r - range_l + 1) + range_l;
return arr;
}
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
template
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
template
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<
main.cpp
#include
#include
#include "SortTestHelper.h"
#include "SelectionSort.h"
using namespace std;
template
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 寻找元素arr[i]合适的插入位置
// 写法1
// for( int j = i ; j > 0 ; j-- )
// if( arr[j] < arr[j-1] )
// swap( arr[j] , arr[j-1] );
// else
// break;
// 写法2
for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
swap( arr[j] , arr[j-1] );
}
return;
}
int main() {
int n = 10000;
cout<<"Test for Random Array, size = "<
2-6 Insertion Sort Advance 插入排序算法的改进
main.cpp
#include
#include
#include "SortTestHelper.h"
#include "SelectionSort.h"
using namespace std;
template
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 寻找元素arr[i]合适的插入位置
// 写法1
// for( int j = i ; j > 0 ; j-- )
// if( arr[j] < arr[j-1] )
// swap( arr[j] , arr[j-1] );
// else
// break;
// 写法2
// for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
// swap( arr[j] , arr[j-1] );
// 写法3
T e = arr[i];
int j; // j保存元素e应该插入的位置
for (j = i; j > 0 && arr[j-1] > e; j--) // 提前终止内层循环
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
int main() {
int n = 10000;
// 测试1 一般测试
cout<<"Test for Random Array, size = "<
SortTestHelper.h
#ifndef INC_04_INSERTION_SORT_ADVANCE_SORTTESTHELPER_H
#define INC_04_INSERTION_SORT_ADVANCE_SORTTESTHELPER_H
#include
#include
#include
#include
#include
#include
using namespace std;
namespace SortTestHelper {
int *generateRandomArray(int n, int range_l, int range_r) {
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (range_r - range_l + 1) + range_l;
return arr;
}
int *generateNearlyOrderedArray(int n, int swapTimes){
int *arr = new int[n];
for(int i = 0 ; i < n ; i ++ )
arr[i] = i;
srand(time(NULL));
for( int i = 0 ; i < swapTimes ; i ++ ){
int posx = rand()%n;
int posy = rand()%n;
swap( arr[posx] , arr[posy] );
}
return arr;
}
int *copyIntArray(int a[], int n){
int *arr = new int[n];
copy(a, a+n, arr);
return arr;
}
template
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
template
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
template
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<
2-7 More concerning O(n^2) Sort Algorithms
Selection Sort 选择排序
Insertion Sort 插入排序 有序的接近O(n)
Bubble Sort 冒泡排序
Shell Sort 希尔排序
// Bubble Sort 冒泡排序
#include
#include
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
using namespace std;
template
void bubbleSort( T arr[] , int n){
bool swapped;
//int newn; // 理论上,可以使用newn进行优化,但实际优化效果较差
do{
swapped = false;
//newn = 0;
for( int i = 1 ; i < n ; i ++ )
if( arr[i-1] > arr[i] ){
swap( arr[i-1] , arr[i] );
swapped = true;
// 可以记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
// 实际优化效果较差,因为引入了newn这个新的变量
//newn = n;
}
//n = newn;
// 优化,每一趟Bubble Sort都将最大的元素放在了最后的位置
// 所以下一次排序,最后的元素可以不再考虑
// 理论上,newn的优化是这个优化的复杂版本,应该更有效
// 实测,使用这种简单优化,时间性能更好
n --;
}while(swapped);
}
int main() {
int n = 10000;
// Test for Random Array
cout<<"Test for Random Array, size = "<
// Shell Sort 希尔排序
#include
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "BubbleSort.h"
using namespace std;
template
void shellSort(T arr[], int n){
int h = 1;
while( h < n/3 )
h = 3 * h + 1;
// 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...
while( h >= 1 ){
// h-sort the array
for( int i = h ; i < n ; i ++ ){
// 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
T e = arr[i];
int j;
for( j = i ; j >= h && e < arr[j-h] ; j -= h )
arr[j] = arr[j-h];
arr[j] = e;
}
h /= 3;
}
}
int main() {
int n = 10000;
// Test for Random Array
cout<<"Test for Random Array, size = "<
Chapter 03 Sorting Advance 高级排序算法 O(n*log n) 的排序算法
3-1 Merge Sort 归并排序法
nlogn 比 n^2 快多少?
n^2 | nlogn | faster | |
---|---|---|---|
n = 10 | 100 | 33 | 3 |
n = 100 | 10000 | 664 | 15 |
n = 1000 | 10^6 | 9966 | 100 |
n = 10000 | 10^8 | 132877 | 753 |
n = 100000 | 10^10 | 1660964 | 6020 |
归并排序 Merge Sort
8个元素 每次2分 第三次每个元素单独
log(N) 数量级
3-2 Merge Sort 归并排序法的实现
main.cpp
#include
#include "SortTestHelper.h"
#include "InsertionSort.h"
using namespace std;
// 将arr[l...mid]和arr[mid+1...r]两部分进行归并
template
void __merge(T arr[], int l, int mid, int r){
// 经测试,传递aux数组的性能效果并不好
T aux[r-l+1];
for( int i = l ; i <= r; i ++ )
aux[i-l] = arr[i];
int i = l, j = mid+1;
for( int k = l ; k <= r; k ++ ){
if( i > mid ) { arr[k] = aux[j-l]; j ++;}
else if( j > r ){ arr[k] = aux[i-l]; i ++;}
else if( aux[i-l] < aux[j-l] ){ arr[k] = aux[i-l]; i ++;}
else { arr[k] = aux[j-l]; j ++;}
}
}
// 递归使用归并排序,对arr[l...r]的范围进行排序
template
void __mergeSort(T arr[], int l, int r){
if( l >= r )
return;
int mid = (l+r)/2;
__mergeSort(arr, l, mid);
__mergeSort(arr, mid+1, r);
__merge(arr, l, mid, r);
}
template
void mergeSort(T arr[], int n){
__mergeSort( arr , 0 , n-1 );
}
int main() {
int n = 50000;
// 测试1 一般性测试
cout<<"Test for Random Array, size = "<
SortTestHelper 和之前的一样 INC_04_INSERTION_SORT_ADVANCE_SORTTESTHELPER_H改为 INC_02_MERGE_SORT_SORTTESTHELPER_H
3-3 Merge Sort Advance 归并排序法的优化
#include
#include "SortTestHelper.h"
#include "InsertionSort.h"
#include "MergeSort.h"
using namespace std;
// 递归使用归并排序,对arr[l...r]的范围进行排序
template
void __mergeSort2(T arr[], int l, int r){
// 对于小规模数组,使用插入排序
if( r - l <= 15 ){
insertionSort(arr, l, r);
return;
}
int mid = (l+r)/2;
__mergeSort2(arr, l, mid);
__mergeSort2(arr, mid+1, r);
// 对于arr[mid] <= arr[Qmid+1]的情况,不进行merge
// 对于近乎有序的数组非常有效,但是对于一般情况,有一定的性能损失
if( arr[mid] > arr[mid+1] )
__merge(arr, l, mid, r);
}
template
void mergeSort2(T arr[], int n){
__mergeSort2( arr , 0 , n-1 );
}
int main() {
int n = 50000;
// 测试1 一般性测试
cout<<"Test for Random Array, size = "<
3-4 Merge Sort Bottom Up 自底向上的归并排序算法
main.cpp
#include
#include "SortTestHelper.h"
#include "MergeSort.h"
using namespace std;
template
void mergeSortBU(T arr[], int n){
// for( int sz = 1; sz <= n ; sz += sz )
// for( int i = 0 ; i < n ; i += sz+sz )
// // 对 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 进行归并
// __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
// Merge Sort Bottom Up 优化
for( int i = 0 ; i < n ; i += 16 )
insertionSort(arr,i,min(i+15,n-1));
for( int sz = 16; sz <= n ; sz += sz )
for( int i = 0 ; i < n - sz ; i += sz+sz )
if( arr[i+sz-1] > arr[i+sz] )
__merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
}
int main() {
int n = 1000000;
cout<<"Test for Random Array, size = "<
3-5 快速排序法 - Quick Sort
3-6 随机化快速排序法
3-7 双路快速排序法