标签:
本文辑录了《算法之美——隐匿在数据结构背后的语言(C++版)》(电子工业出版社2016年出版)一书第11章之代码(P375~P406)。全文目录、“45个算法”目录、“22个经典问题目录”,以及有奖捉虫活动详情请见如下链接:http://blog.csdn.net/baimafujinji/article/details/50484348
附录中的经典笔试、面试问题参考答案请见:
http://blog.csdn.net/baimafujinji/article/details/50484683
In general, 我不太喜欢翻开一本书(技术书),里面密密麻麻的全部都是代码。所以我也希望能够在我的书中留下更多空间去讨论原理和思路。当然,代码也很重要,所有的一切原理最终都要落实到代码上。为此我习惯于在博客中上传代码,而非是把他们全部罗列到书中去挤占篇幅。最后,我仍然建议那些有心学好算法和数据结构的同学彻底击破书中涉及到的算法原理,做到知其然更知其所以然,只有这样你才算是真正学到了东西,也只有这样,你在遇到新的编程问题时才不会束手无策。
如果你是该书的读者,强烈建议你加入算法学习群(495573865),内有更多资源等你,而你在读书中遇到的疑问也将得到我第一时间的解答。更多关注本博客,我将陆续发布该书全部源代码至本博客。
P379 直接插入排序
InsertSort.h
#ifndef INSERTSORT_H #define INSERTSORT_H #include <vector> using namespace std; class InsertSort { private: int len; vector<int> list; public: InsertSort(vector<int> _list, int _len); void insert_sort(); void out(); }; #endif
#include "InsertSort.h" #include <iostream> using namespace std; InsertSort::InsertSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //直接插入排序 void InsertSort::insert_sort() { int insertNum; for (int i=0; i<len; i++) { insertNum = list[i]; // 待插入元素 int j = i; while (j>0 && insertNum<list[j-1]) // 寻找插入位置 { list[j] = list[j-1]; j--; } list[j] = insertNum; } } void InsertSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P381 二分插入排序
BinaryInsertSort.h
#ifndef BINARYINSERTSORT_H #define BINARYINSERTSORT_H #include <vector> using namespace std; class BinaryInsertSort { private: int len; vector<int> list; public: BinaryInsertSort(vector<int> _list, int _len); void binary_insert_sort(); void out(); }; #endif
#include "BinaryInsertSort.h" #include <iostream> using namespace std; BinaryInsertSort::BinaryInsertSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //2 二分插入排序 void BinaryInsertSort::binary_insert_sort() { int middle; for (int i=0; i<len; i++) { int insertNum = list[i]; int left = 0; int right = i-1; while (left <= right) //二分法寻找插入位置 { middle = (left + right)/2; if (insertNum > list[middle]) left = middle+1; else right = middle-1; } for (int j=i; j>left; j--) list[j] = list[j-1]; list[left] = insertNum; } } void BinaryInsertSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P383 希尔排序
ShellSort.h
#ifndef SHELLSORT_H #define SHELLSORT_H #include <vector> using namespace std; class ShellSort { private: int len; vector<int> list; public: ShellSort(vector<int> _list, int _len); void shell_sort(); void out(); }; #endif
ShellSort.cpp
#include "ShellSort.h" #include <iostream> using namespace std; ShellSort::ShellSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //3 希尔排序------------------------------------------------------------ void ShellSort::shell_sort() { int insertNum; int gap = len/2; //初始增量 while (gap) //当gap>=1 { for (int i=gap; i<len; i++) //对gap间隔子序列进行插入排序 { insertNum = list[i]; //待插入元素 int j = i; while (j>=gap && insertNum<list[j-gap]) { //寻找插入位置 list[j] = list[j-gap]; j -= gap; } list[j] = insertNum; //插入 } gap = gap/2; //缩小增量 } } void ShellSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P385 直接选择排序
SelectSort.h
#ifndef SELECTSORT_H #define SELCETSORT_H #include <vector> using namespace std; class SelectSort { private: int len; vector<int> list; public: SelectSort(vector<int> _list, int _len); void select_sort(); void swap(int,int); void out(); }; #endif
SelectSort.cpp
#include "SelectSort.h" #include <iostream> using namespace std; SelectSort::SelectSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //4 直接选择排序 ------------------------------------------------------- void SelectSort::select_sort() { int k; for (int i=0; i<len; i++) { k = i; for (int j=i+1; j<len; j++) // 找最小元素 if (list[j] < list[k]) k = j; swap(i, k); // 将最小元素放入i位置 } } void SelectSort::swap(int i, int j) { int temp = list[i]; list[i] = list[j]; list[j] = temp; } void SelectSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P388 堆排序
HeapSort.h
#ifndef HEAPSORT_H #define HEAPSORT_H #include <vector> using namespace std; class HeapSort { private: int len; vector<int> list; public: HeapSort(vector<int> _list, int _len); void heap_sort(); void filterDown(int current, int last); void swap(int,int); void out(); }; #endif
HeapSort.cpp
#include "HeapSort.h" #include <iostream> using namespace std; HeapSort::HeapSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } // 堆排序 void HeapSort::heap_sort() { for (int i=(len-2)/2; i>=0; i--) filterDown(i, len-1);//建立堆 for (int i=len-1; i>0; i--) { swap(0, i); filterDown(0, i-1); //不断调整堆为最大堆 } } // 堆的建立或调整 void HeapSort::filterDown(int current, int last) { int child = 2*current+1; //child为current的子女位置 int temp = list[current]; //暂存子树根结点 while (child <= last) //判断是否到最后结尾 { if (child<last && list[child]<list[child+1]) child++; //让child指向两子女中的大者 if (temp >= list[child]) break; //temp的关键码大则不做调整 else //否则子女中的大者上移 { list[current] = list[child]; current = child; child = 2*child+1; } } list[current] = temp; //temp中暂存元素放到合适位置 } void HeapSort::swap(int i, int j) { int temp = list[i]; list[i] = list[j]; list[j] = temp; } void HeapSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P391 冒泡排序
BubbleSort.h
#ifndef BUBBLESORT_H #define BUBBLESORT_H #include <vector> using namespace std; class BubbleSort { private: int len; vector<int> list; public: BubbleSort(vector<int> _list, int _len); void bubble_sort(); void swap(int,int); void out(); }; #endif
BubbleSort.cpp
#include "BubbleSort.h" #include <iostream> using namespace std; BubbleSort::BubbleSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //6 冒泡排序 void BubbleSort::bubble_sort() { for (int i=0; i<len; i++) for (int j=i+1; j<len; j++) if (list[i] > list[j]) swap(i, j); } void BubbleSort::swap(int i, int j) { int temp = list[i]; list[i] = list[j]; list[j] = temp; } void BubbleSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P393 鸡尾酒排序
ShakerSort.h
#ifndef SHAKERSORT_H #define SHAKERSORT_H #include <vector> using namespace std; class ShakerSort { private: int len; vector<int> list; public: ShakerSort(vector<int> _list, int _len); void shaker_sort(); void swap(int,int); void out(); }; #endif
ShakerSort.cpp
#include "ShakerSort.h" #include <iostream> using namespace std; ShakerSort::ShakerSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //7 Shaker排序------------------------------------------------------------ void ShakerSort::shaker_sort() { int i, left = 0, right = len - 1,shift = 0; while(left < right) { for(i = left; i < right; i++) //向右进行气泡排序 { if(list[i] > list[i+1]) { swap(i, i+1); shift = i; } } right = shift; for(i = right; i > left; i--) //向左进行气泡排序 { if(list[i] < list[i-1]) { swap(i ,i-1); shift = i; } } left = shift; } } void ShakerSort::swap(int i, int j) { int temp = list[i]; list[i] = list[j]; list[j] = temp; } void ShakerSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
QuickSort.h
#ifndef QUICKSORT_H #define QUICKSORT_H #include <vector> using namespace std; class QuickSort { private: int len; vector<int> list; public: QuickSort(vector<int> _list, int _len); void quick_sort(int,int); void swap(int,int); void out(); }; #endif
#include "QuickSort.h" #include <iostream> using namespace std; QuickSort::QuickSort(vector<int> _list, int _len) { for (int i=0; i<_len; i++) list.push_back(_list[i]); this->len = _len; } //8 快速排序------------------------------------------------------------ void QuickSort::quick_sort(int left, int right) { int i = left; int j = right; int pivot = list[left]; while (i<j) { while (i<j && list[j]>=pivot) j--; //找到比基数小的元素 if(i < j) swap(i, j); while (i<j && list[i]<=pivot) i++; //找到比基数大的元素 if(i < j) swap(i, j); } if (i!=left) quick_sort(left, i-1); //对list[left...i-1]排序 if (j!=right) quick_sort(j+1, right); //对list[j+1...right]排序 } void QuickSort::swap(int i, int j) { int temp = list[i]; list[i] = list[j]; list[j] = temp; } void QuickSort::out() { for (int i=0; i<len; i++) { cout<< list[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
P401 归并排序
MergeSort.h
#define MERGESORT_H #include <vector> using namespace std; class MergeSort { private: int len; vector<int> list; vector<int> link; public: MergeSort(vector<int> _list, int _len); int merge_sort(int,int); int list_merge(int,int); void out(); }; #endif
#include "MergeSort.h" #include <iostream> using namespace std; MergeSort::MergeSort(vector<int> _list, int _len) { list.push_back(0); link.push_back(0); for (int i=0; i<_len; i++) { list.push_back(_list[i]); link.push_back(0); } this->len = _len; } //9 归并排序:递归----------------------------------------------------------- //具体方法:以merger_link[]提供链表功能。merger_link[i]对应在有序子序列中 //merger_list[i]后一个结点在原merger_list[]中的下标; //merger_link[0]总是表示有序子序列开始的结点在merge_list[]中的下标; //st1,st2为两个有序序列的第一个结点; //将他们归并,并返回其第一个结点的下标,即merger_link[0] int MergeSort::list_merge(int st1, int st2) { int k = 0, i = st1, j = st2; while (i && j) //当两序列未检测完 if (list[i] <= list[j]) //将merge_list[i]和merge_list[j] { //中小的连接到merger_link[k]后 link[k] = i; k = i; i = link[i]; }else { link[k] = j; k = j; j = link[j]; } if (!i) link[k] = j; //将剩余未检测完的merge_list[] else link[k] = i; //连接到merger_link[k]后 return link[0]; } int MergeSort::merge_sort(int left, int right) { if (left>=right) return left; int middle = (left + right)/2; //对左右两子序列进行归并 return list_merge(merge_sort(left,middle), merge_sort(middle+1,right)); } void MergeSort::out() { int i = link[0]; int j = 0; while (i) { j++; cout<< list[i] <<" "; i = link[i]; if (j%18 == 0) cout <<endl; } cout <<endl; }
P405 计数排序
CountingSort.h
#ifndef COUNTINGSORT_H #define COUNTINGSORT_H #include <vector> using namespace std; class CountingSort { private: int len; int max; vector<int> list; vector<int> result; //保存结果 public: CountingSort(vector<int> _list, int _len, int _max); void counting_sort(); void out(); }; #endif
CountingSort.cpp
#include "CountingSort.h" #include <iostream> using namespace std; CountingSort::CountingSort(vector<int> _list, int _len, int _max) { this->max = _max; this->len = _len; for (int i=0; i<_len; i++) { list.push_back(_list[i]); result.push_back(0); if (_list[i] > max) { cout<< "数据超出范围!"<<endl; return; } } } //10 计数排序 void CountingSort::counting_sort() { int* mark = new int[max]; //标记无序表中元素 memset(mark, 0, max * sizeof(int)); for (int i = 0; i < len; i++) mark[list[i]]++; //统计元素出现次数 for (int i = 1; i < max; i++) mark[i] += mark[i-1]; //计算元素在有序表中位置 for (int i = len - 1; i >= 0; i--) { result[mark[list[i]] - 1] = list[i];//通过mark[]直接将list[i] mark[list[i]]--; //有序存入result[] } delete []mark; } void CountingSort::out() { for (int i=0; i<len; i++) { cout<< result[i] << " "; if ((i+1)%18 == 0) cout<<endl; } cout <<endl; }
另附测试程序主函数
#include <iostream> #include <vector> #include "InsertSort.h" #include "BinaryInsertSort.h" #include "ShellSort.h" #include "SelectSort.h" #include "BubbleSort.h" #include "HeapSort.h" #include "ShakerSort.h" #include "QuickSort.h" #include "MergeSort.h" #include "CountingSort.h" #define MAX 1000 using namespace std; int main() { //读入无序表----------------------------- vector<int> list; int len, inp; cout<<"请输入序列个数(0退出):"; cin >>len; if (len == 0) exit(0); cout<<"请输入待排序列:"; for (int i=0; i<len; i++) { cin >> inp; list.push_back(inp); } // 以下是十种常用快速排序---------------- //1. 直接插入排序 //2. 二分插入排序 //3. 希尔排序 //4. 直接选择排序 //5. 堆排序 //6. 冒泡排序 //7. Shaker排序 //8. 快速排序 //9. 归并排序 //10.计数排序 InsertSort sort1(list, len); sort1.insert_sort(); sort1.out(); BinaryInsertSort sort2(list, len); sort2.binary_insert_sort(); sort2.out(); ShellSort sort3(list, len); sort3.shell_sort(); sort3.out(); SelectSort sort4(list,len); sort4.select_sort(); sort4.out(); HeapSort sort5(list, len); sort5.heap_sort(); sort5.out(); BubbleSort sort6(list, len); sort6.bubble_sort(); sort6.out(); ShakerSort sort7(list, len); sort7.shaker_sort(); sort7.out(); QuickSort sort8(list, len); sort8.quick_sort(0, len-1); sort8.out(); MergeSort sort9(list, len); sort9.merge_sort(1,len); sort9.out(); CountingSort sort10(list, len, MAX);// MAX为用户提供的无序表最大范围 sort10.counting_sort(); sort10.out(); system("PAUSE"); }
内容简介:探秘算法世界,求索数据结构之道;汇集经典问题,畅享编程技法之趣;点拨求职热点,敲开业界名企之门。本书围绕算法与数据结构这个话题,循序渐进、深入浅出地介绍了现代计算机技术中常用的四十余个经典算法,以及回溯法、分治法、贪婪法和动态规划等算法设计思想。在此过程中,本书也系统地讲解了链表(包括单向链表、单向循环链表和双向循环链表)、栈、队列(包括普通队列和优先级队列)、树(包括二叉树、哈夫曼树、堆、红黑树、AVL树和字典树)、图、集合(包括不相交集)与字典等常用数据结构。同时,通过对二十二个经典问题(包括约瑟夫环问题、汉诺塔问题、八皇后问题和骑士周游问题等)的讲解,逐步揭开隐匿在数据结构背后的算法原理,力图帮助读者夯实知识储备,激活思维技巧,并最终冲破阻碍编程能力提升的重重藩篱。辅有完整的C++源代码,并穿插介绍了STL中的各种容器。
网上书店:
China-pub中国互动出版网:http://product.china-pub.com/4911922
当当网:http://product.dangdang.com/23851244.html
亚马逊:http://www.amazon.cn/%E7%AE%97%E6%B3%95%E4%B9%8B%E7%BE%8E-%E9%9A%90%E5%8C%BF%E5%9C%A8%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E8%83%8C%E5%90%8E%E7%9A%84%E5%8E%9F%E7%90%86-%E5%B7%A6%E9%A3%9E/dp/B01AGNUIE8/ref=sr_1_8?ie=UTF8&qid=1453527399&sr=8-8&keywords=%E5%B7%A6%E9%A3%9E
至此,《算法之美————隐匿在数据结构背后的语言(C++版)》一书的全部代码皆已发布完毕,全部代码目录可以参见:
http://blog.csdn.net/baimafujinji/article/details/50676557
标签:
原文地址:http://blog.csdn.net/baimafujinji/article/details/50641354