文章分类 - 数据结构
摘要:在《二分查找法的实现和应用汇总》中,我介绍了二分查找法的基本应用,不过在面试的准备过程中,我还碰到了更多对于二分查找法的更进一步的使用。其实在《二分查找法的实现和应用汇总》的最后,我已经介绍了一个非常规的使用,也就是基于“轮转后的有序数组(Rotated Sorted Array)”检查某一个数是否存在。找到轮转后的有序数组中第K小的数对于普通的有序数组来说,这个问题是非常简单的,因为数组中的第K-1个数(即A[K-1])就是所要找的数,时间复杂度是O(1)常量。但是对于轮转后的有序数组,在不知道轮转的偏移位置,我们就没有办法快速定位第K个数了。不过我们还是可以通过二分查找法,在log(n)的
阅读全文
摘要:在学习算法的过程中,我们除了要了解某个算法的基本原理、实现方式,更重要的一个环节是利用big-O理论来分析算法的复杂度。在时间复杂度和空间复杂度之间,我们又会更注重时间复杂度。时间复杂度按优劣排差不多集中在:O(1), O(log n), O(n), O(n log n), O(n2), O(nk), O(2n)到目前位置,似乎我学到的算法中,时间复杂度是O(log n),好像就数二分查找法,其他的诸如排序算法都是 O(n log n)或者O(n2)。但是也正是因为有二分的 O(log n), 才让很多 O(n2)缩减到只要O(n log n)。关于二分查找法二分查找法主要是解决在“一堆数中找
阅读全文
摘要:那么在递归形式的2-路归并排序中,会不停的申请容量为count的int数组,在递归调用中会占用大量的存储空间。为了节省存储空间的开销,可以考虑非递归的形式。// 归并排序之非递归void CMergingSort::MergeSort(void){ constint count =9; int A[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; int step =1; int B[count] = {0}; //决定趟数while (step < count) { MergePass(A, B, ...
阅读全文
摘要:内部排序,还有一个基数排序,基数排序也是比较常用的。有时间再好好研究一下,先把排序源代码上传。http://files.cnblogs.com/wanggary/SortPlusPlus.zip
阅读全文
摘要:归并排序(Merging Sort),是又一类不同的排序方法。“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。时间复杂度为O(nlog2n)。constint count =9;// 2-路归并排序之递归形式void CMergingSort::Path2MergingSort(void){ int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; MSort(L, L, 1, count -1); //打印排序结果。for (int i =0; i < count; ++ i) { cout ...
阅读全文
摘要:堆排序(Heap Sort),只需要一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间。堆的定义如下:n个元素的序列{k1, k2, … , kn}当且仅当满足下关系时,称之为堆。Ki <= K2i && Ki <= K2i+1 或 Ki >= K2i && Ki >= K2i+1,(i = 1, 2, … , n/2」)。若将和此序列对应的一维数组看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。理解
阅读全文
摘要:树形选择排序(Tree Selection Sort),又称锦标赛排序(Tournament Sort),是一种按锦标赛的思想进行选择排序的方法。时间复杂度为O(nlog2n)。理解:两两比较,选出第一个最小值,将原来的叶子节点设置为∞,进行同样的两两比较,既可选出第二个最小值,如此往复。缺点:占用的辅助存储空间较多,和“∞”进行多余的比较等。为了弥补这些缺点J.willioms提出了另一种形式的选择排序——堆排序。 首先将待排序记录两两分组,将每组的最小值设置为他们的父结点,把所有这些筛选出来的父结点再两两分组,选出每组的最小值并设置为这组的父结点。一层一层筛选,直到选出根结点,就是最小值.
阅读全文
摘要:简单选择排序(Simple Selection Sort),一趟简单选择排序的操作为:通过n - i 次关键字间的比较,从n - i + 1个记录中选出关键字最小的记录,并和第i(1 <= i <= n)个记录交换之。时间复杂度为O(n^2)。// 简单选择排序void CSelectionSort::SimpleSelectionSort(void){ constint count =9; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; for (int i =0; i < count; ++i) { ...
阅读全文
摘要:快速排序(Quick Sort)是对起泡排序的一种改进。它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。// 快速排序void CExchangeSort::QuickSort(void){ constint count =9, length = count -1; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; int low =1; int high = length; QuickSor...
阅读全文
摘要:起泡排序(Bubble Sort),依次比较相邻的两个记录的关键字,逆序时交换,一趟比较后最大的记录被安置到最后一个记录的位置上。时间复杂度为O(n^2)。void CExchangeSort::BubbleSort(void){ constint count =9, length = count -1; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; bool change =true; for (int i = count -1; i >0&& change; -- i) { change...
阅读全文
摘要:希尔排序(Shell’s Sort)又称“缩小增量排序”(Diminishing Increment Sort),它也是一种属于插入排序类的方法,但在时间效率上较前述几种排序方法有较大的改进。时间复杂度为O(n^3/2)。理解:先将整个待排记录序列分割成为若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。void CInsertionSort::ShellSort(void){ constint count =9, length = count -1; int L[count] = {0, 49, 38, 65, 97, 76...
阅读全文
摘要:若希望在排序过程中不移动记录,只有改变存储结构,进行表插入排序。存储结构定义如下:#define SIZE 100 //静态链表容量typedef struct { string rc; //记录项int next; //指针项}SLNode; //表结点类型typedef struct{ SLNode r[SIZE]; //0号单元为表头结点int length; //链表当前长度}SLinkListType; //静态链表类型 为了方便插入,设数组中下标为“0”的分量为表头结点,并...
阅读全文
摘要:2-路插入排序是在折半插入排序的基础上再改进之,其目的是减少排序过程中移动记录的次数,但为此需要n个记录的辅助空间。时间复杂度为O(n^2)。理解:所谓的2-路,是指优先插入在序列前面或后面,然后再考虑插入到中间。void CInsertionSort::Path2Insertion(void){ //元素0是哨兵。constint count =9, length = count -1; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; //对顺序表L作2-路插入排序。int d[length] = { 0 }; ...
阅读全文
摘要:由于插入排序的基本操作是在一个有序表中进行查找和插入,这个“查找”操作可利用“折半查找”来实现,由此进行的插入排序称之为折半插入排序(Binary Insertion Sort)。时间复杂度为O(n^2)。理解:依次将每个待排序的记录插入到一个有序序列的合适位置。插入的位置是采用折半查找法确定的。void CInsertionSort::BinaryInsertion(void){ //元素0是哨兵。constint count =9; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; //对顺序表L作折半插入排序。f...
阅读全文
摘要:直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。时间复杂度为O(n^2)。理解:依次将每个待排序的记录插入到一个有序序列的合适位置。插入的位置是和有序序列的每一个元素进行比较,然后确定的。void CInsertionSort::StraightInsertion(void){ //元素0是哨兵。constint count =9; int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49}; //对顺序表作...
阅读全文
摘要:P263 排序(Sorting)是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。 为了便于讨论,在此首先要对排序下一个确切的定义: 假设含n个记录的序列为:{ R1, R2, ... , Rn },其相应的关键字序列为:{ K1, K2, ... , Kn },需确定1, 2, ... , n的一种排列p1, p2, ... , pn,使其相应的关键字满足如下的非递减(或非递增)关系:Kp1 <= Kp2 <= ... <= Kpn,使序列成为一个按关键字有序的序列:{ Rp1, Rp2, ... , Rpn
阅读全文
摘要:算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。而度量一个程序的执行时间通常有两种方法。(1)事后统计的方法。(2)事 前分析估算的方法。因事后统计方法更多的依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优劣。因此人们常常采用事前分析估算的方法。两个N * N矩阵相乘。如 2 * 2的矩阵,void CMatrixNN::ComputeN2(void){ const int n = 2; int a[n][n] = { {1, 2}, {1, 2} }; int b[n][n] = { {1, 2}, {1, 2} }; int ...
阅读全文