第二小元素

一、题目

证明:在最坏情况下,利用n+ceil(lgn)-2次比较,即可得到n个元素中的第2小元素。(提示:同时找最小元素)

二、思考

step1:对所有元素,两个一组比较大小,小的一个进入下一轮比较。一直到比较出最小的元素。此时所有比较结果构成一棵二叉树。比较次数为n-1。

step2:沿着树从树根向下到叶子,找出第二小的元素,比较次数是ceil[lgn]-1。令m2[p]表示以p为根的树中的第二小元素。对于当前处理结点为p,key[p] = min{key[left[p]], key[right[p]]}。假设key[p] =  key[left[p]],则m2[p] = min{m2[left[p]], key[right[p]]}


三、代码

[cpp]  view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3. //第一遍求最小值的结果用树表示  
  4. struct node  
  5. {  
  6.     int key;  
  7.     node *next;//指向同一层中的下一个元素  
  8.     node *p;  
  9.     node *left;  
  10.     node *right;  
  11.     node(int k):key(k),next(NULL),p(NULL),left(NULL),right(NULL){}  
  12. };  
  13. //求第二小值  
  14. int Find_S2(node *head)  
  15. {  
  16.     node *p, *q, *r, *t;  
  17.     //step1:求最小值  
  18.     //两两比较,较小的一个进入下一轮,这个循环当只剩下一个元素时结束  
  19.     while(head->next != NULL)  
  20.     {  
  21.         //从第一个元素开始,head指向比完后较小的那一组数据中的第一个  
  22.         p = head;head = NULL;  
  23.         while(p)  
  24.         {  
  25.             //如果这组数据有奇数个,最后一个元素直接晋级  
  26.             if(p->next == NULL)  
  27.             {  
  28.                 r = new node(p->key);  
  29.                 r->left = p;  
  30.                 p->p = r;  
  31.                 p = p->next;  
  32.             }  
  33.             //p与p->next比较,较小的元素晋级  
  34.             else  
  35.             {  
  36.                 q = p->next;  
  37.                 r = new node(min(p->key, q->key));  
  38.                 r->left = p;  
  39.                 r->right = q;  
  40.                 p->p = r;  
  41.                 q->p = r;  
  42.                 p = q->next;  
  43.             }  
  44.             //head指向比完后较小的那一组数据中的第一个,t用于把head指向的数据链成链表  
  45.             if(head == NULL)  
  46.             {  
  47.                 head = r;  
  48.                 t=  head;  
  49.             }  
  50.             else  
  51.             {  
  52.                 t->next = r;  
  53.                 t = r;  
  54.             }  
  55.         }  
  56.     }  
  57.     //step2:求最第二小值  
  58.     //Min用于存储最小值,Min2用于存储第二小值  
  59.     int Min = head->key, Min2 = 0x7fffffff;  
  60.     //从根结点向下比较  
  61.     p = head;  
  62.     //比较到叶子结点时循环结束  
  63.     while(p->left != NULL)  
  64.     {  
  65.         //当前结点的值来源于右孩子  
  66.         if(p->right && p->right->key == Min)  
  67.         {  
  68.             Min2 = min(Min2, p->left->key);  
  69.             p = p->right;  
  70.         }  
  71.         //当前结点的值来源于左孩子  
  72.         else  
  73.         {  
  74.             //由左孩子直接晋级的情况  
  75.             if(p->right)  
  76.                 Min2 = min(Min2, p->right->key);  
  77.             p = p->left;  
  78.         }  
  79.     }  
  80.     return Min2;  
  81. }  
  82. //测试  
  83. int main()  
  84. {  
  85.     int A[8] = {0};  
  86.     node *head = NULL;  
  87.     //生成8个随机测试数据  
  88.     for(int i = 0; i < 8;i++)  
  89.     {  
  90.         A[i] = rand() % 100;  
  91.         //构造成树的最底层结点  
  92.         node *p = new node(A[i]);  
  93.         p->next = head;  
  94.         head = p;  
  95.     }  
  96.     //运行算法并输出结果  
  97.     cout<<Find_S2(head)<<endl;  
  98.     return 0;  
  99. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值