堆排序.K路合并.杨氏矩阵

原创 2007年10月15日 18:55:00

一.堆排序.

     以前虽然对堆排序的理论和过程已经非常熟悉了,伪代码也写了不少,但竟然还没有真正在VC中实现过.今天把它写了一下,代码如下:

#include<iostream>
using namespace std;

//======================================
//  最大堆 Heap
//======================================
class Heap
{
    
private:
        
int *array;
        size_t size;
        inline size_t parent(size_t i)
        {
            
return i>>1;
        }
        inline size_t left(size_t i)
        {
            
return i<<1;
        }
        inline size_t right(size_t i)
        {
            
return (i<<1)+1;
        }
    
public:
        Heap(
int *array,size_t size)
        {
            
this->array=array;
            
this->size=size;
        }
        
void heapify(size_t i)
        {
            size_t l,r,max
=i;
            
int temp;
            l
=left(i);
            r
=right(i);
            
if(l<size && array[i]<array[l]) max=l;
            
if(r<size && array[max]<array[r]) max=r;
            
if(max!=i)
            {
                temp
=array[i];
                array[i]
=array[max];
                array[max]
=temp;
                heapify(max);
            }
        }
        
void buildHeap()
        {
            
for(int i=parent(size-1);i>=0;i--)
                heapify(i);
        }
        
void sort()
        {
            
int temp;
            
for(int i=size-1;i>0;i--)
            {
                temp
=array[0];
                array[
0]=array[i];
                array[i]
=temp;
                size
=size-1;
                heapify(
0);
            }
        }    
};


//一个简单的应用实例------------------
void main()
{
    
int a[10]={2,6,3,8,9,7,1,4,0,5};
    Heap heap
=Heap(a,10);
    heap.buildHeap();
    heap.sort();
    
for(int i=0;i<10;i++)
    {
        cout
<<a[i]<<endl;;
    }
    
}

 

 二.基于堆的K路合并问题.

题:请给出一下时间为O(n*lgk),用来将 k 个已排序链表合并为一个排序链表的算法.此处,n 次所有输入链表中元素的总数.

答:新建一个链表,再申请一个大小为 k 的数组A,首先把 k 个已排序链表的第一个元素压入 A 中,将 A 建成一个最小堆,花费O(k) 的时间.然后将堆 A 的第一个元素 min(也就是最小的那个)放入链表中.再将min->nextNode 放在min的位置.再花O(lgk)调用heapify 方法将 A 重新建成一个最小堆.然后又将第一个元素 min 放入链表......重复进行就可将 k 个已排序链表合并.(当最后剩余不到 k 个节点时情况会有点变化,但很容易解决).显然,这样处理的时间复杂为 O(n*lgk);

 三.Young 氏矩阵的相关算法.

题:一个 m*n 的 Young 氏矩阵(Young tableau) 是一个 m*n 的矩阵,其中每一行的数据都从左到右排序,第一列的数据都从上到下排序.Young 氏矩阵中可能会有一些  ∞ 数据项,表示不存在的元素.所以,Young 氏矩阵可以用来存放 r<= mn 个有限的元素.

a).画一个包含{9,16,3,2,4,8,5,14,12} 的4*4 的Young 氏矩阵.

b).给出一个在非空 m*n 的 Young  氏矩阵上实现 EXTRACT-MIN 算法,使其运行时间为O(m+n).

c).说明如何在O(m+n)时间内,将一个新元素手入到一个未满的 m*n Young 氏矩阵中.

d).给出一个时间复杂度为 O(n^3) 的对 n*n Young 氏矩阵排序的算法.

f).给出一个运行时间为O(m+n) 的算法,来决定一个给定的数是否存在于一个给定的 m*n  的 Young 氏矩阵当中.

答.a).  2     3      4      5

          8     9     12    14

         16    ∞      ∞     ∞

          ∞     ∞      ∞     ∞        PS.该矩阵并不是唯一的.

    b). 用递归的思想.通过递归的解决(m-1)*n,或m*(n-1) 的子问题来求解.则有 T(m,n)=T(m-1,n) or T(m,n-1)+ O(1),显然,T=O(m+n).伪代码如下:

EXTRACT_MIN( Young[ x...m] [y...n])
   EXTRACT_MIN
=Young[x][y]; //类似FORTRAN的写法.函数名即是返回值.
   if(x==m and y==n) Young[x][y]= INFINITY;
   
if(Young[x+1][y]>Young[x][y+1])
          Young[x][y]
=EXTRACT_MIN(Young[x...m][y+1...m]);
   
else Young[x][y]=EXTRACT_MIN(Young[x+1...m][y...m]);
END

      c).  这个就比较简单了.先将待插入的元素 K 放在 Young[m][n], 然后比较 K 与它左方或上方元素的大小,并与其中较大的一个交换.反复进行直到 K 不小于它左方和上方的元素为止. 在这里,同样有,T(m,n)=T(m-1,n) or T(m,n-1)+ O(1),T=O(m+n).伪代码如下:

INSERT(k,Young[m][n])
  
if(Young[m][n] < INFINITY)  alert: 矩阵已满,无法插入!!
  
while(k<Young[m-1][n] or k<Young[m][n-1])
      
if(Young[m-1][n] >Young[m][n-1])
          swap(k,Young[m
-1][n]);
          m
=m-1;
      
else
          swap(k,Young[m][n
-1]);
          n
=n-1;
END

            

     d). 调用 n*n 次 EXTRACT_MIN 过程即可.

       e). 同样是递归的思想.递归表达式与 b)中的相同.伪代码如下:

SEARCH(k,Young[x...m][y...n]
    
if(k<Young[x][y] or k>Young[m][n] return "NotFound";
    
if(k==Young[x][y])    return "Found",x,y.
    
if(k<Young[x+1][y]) SEARCH(k,Young[x...x][y+1...n]
    
else SEARCH(k,Young[x+1...m][y...n]
END

[算法系列之三十三]杨氏矩阵

编写一个有效的算法,搜索一个值在一个n x m表(二维数组)。这张表是沿着行和列进行--排序,也就是:                                                 ...
  • SunnyYoona
  • SunnyYoona
  • 2013年11月28日 23:15
  • 1985

杨氏矩阵与钩子公式

杨氏矩阵又叫杨氏图表,它是这样一个矩阵,满足条件:   (1)如果格子(i,j)没有元素,则它右边和上边的相邻格子也一定没有元素。 (2)如果格子(i,j)有元素a[i][j],则它右边和上边的相邻格...
  • ACdreamers
  • ACdreamers
  • 2013年11月08日 21:33
  • 6086

第二十三章:杨氏矩阵查找、排序、添加、删除

Young氏矩阵 在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 ...
  • starcuan
  • starcuan
  • 2014年02月10日 23:51
  • 936

杨氏矩阵搜索算法

2013-05-21 09:53 29人阅读 评论(0) 收藏 举报 问题:已知一个2维矩阵,其中的元素每一行从左至右依次增加,每一列从上到下依次增加。即对于矩阵Table有Table[i]...
  • pi9nc
  • pi9nc
  • 2013年06月13日 10:35
  • 1272

杨氏矩阵与钩子公式

杨氏矩阵又叫杨氏图表,它是这样一个矩阵,满足条件:   (1)如果格子(i,j)没有元素,则它右边和上边的相邻格子也一定没有元素。 (2)如果格子(i,j)有元素a[i][j],则它右边和上边的...
  • u013007900
  • u013007900
  • 2015年07月07日 22:06
  • 985

堆排序及top K 算法

static void swap(int* left,int *right) { int tmp=*left; *left=*right; *right=tmp; } void adjustdo...
  • yangkaikwill
  • yangkaikwill
  • 2015年07月10日 16:52
  • 446

排序算法整理(6)堆排序的应用,top K 问题

top K问题是这样的,给定一组任意顺序的数,假设有n个。如何尽快地找到它们的前K个最大的数? 首先,既然是找前K个最大的数,那么最直观的办法是,n个数全部都排序,然后挑出前K个最大数。但是这样显然做...
  • feliciafay
  • feliciafay
  • 2013年10月03日 12:51
  • 5906

堆排序(最小堆)--【算法导论】

堆排序的思想在堆排序(最大堆)已做说明,故不再赘述; 总之,思想就是首先进行建堆,由于这是最小堆,故而必须保证父节点都小于孩子节点,若不满足条件,则进行调节; 最后进行堆排序,不断将最小的提取出来...
  • xjm199
  • xjm199
  • 2014年01月08日 21:39
  • 4381

用堆排序寻找数组中最大的K个数

/*********************************************************************************** 堆排序(Heapsort)是指...
  • shihui512
  • shihui512
  • 2013年04月22日 15:31
  • 1647

最小堆解决Top K问题

问题描述:有一组数据n个,要求取出这组数据中最大的K个值。 对于这个问题,解法有很多中。比如排序及部分排序,不过效率最高的要数最小堆,它的时间复杂度为O(nlogk)。 解题思路: 取出数组的前n...
  • wangshuang1631
  • wangshuang1631
  • 2016年11月18日 17:11
  • 2202
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:堆排序.K路合并.杨氏矩阵
举报原因:
原因补充:

(最多只允许输入30个字)