Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2563896
  • 博文数量: 315
  • 博客积分: 3901
  • 博客等级: 少校
  • 技术积分: 3640
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-08 15:32
个人简介

知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516

文章分类

全部博文(315)

文章存档

2019年(2)

2018年(1)

2016年(7)

2015年(32)

2014年(39)

2013年(109)

2012年(81)

2011年(44)

分类: C/C++

2012-08-08 01:06:40

   最近在复习C语言,做一些练习,看一些笔试题,顺便学点别人的思想。更重要的是实践下C++,之前也看了书,所以理解下,不会了再回头学习。
  看了下百度的笔试题,有个关于单链表(100万个结点),需要找出属于同一个组的Top10,主要就是排序然后定义一个node_t top[10] 去找到这10个结点就OK了。其中要求不用太多空间又要高效,所以就用堆排序,堆排序不是很熟练,还是理解的,SO拿来主义---虽然不太好!
  顺带练习了下模版,其实在其中模版不应该使用的,因为结构体定义没有通用性,just为了练习下,因此就练习吧。当然还有操作符的重载,学习是永无止尽的。如果自己想得到一个更高的发展,基础应该很重要,我的基础不是很好,能做出来东西,但是质量不会,这点需要像很多高手学习才好。不说了,好好努力吧!

点击(此处)折叠或打开

  1. /*
  2. file: node.h
  3. author: hl
  4. date: 2012-08-07
  5. */
  6. #ifndef NODE_H
  7. #define NODE_H

  8. typedef struct node_t{
  9.      int value; /* 节点排序字段 */
  10.      int group; /* 组号: 0,1,2,3,4,5,6,7,8,9 */
  11.      struct node_t *pnext; /* 下个节点的指针 */
  12. }node_t;
  13. /*Here 我想将成员变量改为template,这样一切变化尽在掌握之中*/
  14. template <typename T, typename W>
  15. struct node_b{
  16.      T value;
  17.      W group;
  18.      struct node_b *next;
  19. };

  20. //没用~
  21. class cmp{
  22. public:
  23.      cmp(){}
  24.      cmp(int& a, int& b) //适合没返回值的operator函数,调用的时候直接new cmp(a, b)就可以完成排序之类的操作;
  25.      {
  26.           swap(a, b);
  27.      }
  28. public:
  29.      inline bool operator () (int a, int b) //比较函数()重载
  30.      {
  31.           return a > b;
  32.      }
  33.      void swap (int& a, int& b)
  34.      {
  35.                a = a ^ b;
  36.                b = a ^ b;
  37.                a = b ^ a;
  38.      }
  39. };

  40. //重载swap
  41. namespace BAIDU
  42. {
  43.      template <typename T>
  44.      class swap_p{
  45.      public:
  46.           void operator () (T& a, T& b)
  47.           {
  48.                T temp;
  49.                temp = a;
  50.                a = b;
  51.                b = temp;
  52.           }
  53.      };
  54. };

  55. template <typename T>
  56. class NodeOperate{
  57. public:
  58.      NodeOperate()
  59.      {
  60.           //you can add initial code here
  61.      }
  62. public:
  63.      void nodeInitial(T *head);
  64.      void nodeInsert(T *head, T& node);
  65.      void nodeCreate(T *head, T arr[], int nodeNumber);
  66.      //调整堆,每次选取一个较大的子节点替换父节点,然后继续处理该较大的子节点!
  67.      inline void heapadjust(T top[], int root, int len)
  68.      {
  69.           int i = root;
  70.           while(2 * i + 1 < len)
  71.           {
  72.                //获取较大的儿子节点,左孩子(2 * i + 1),右孩子(2 * i + 2)
  73.                int child = 2 * i + 1;
  74.                if(child + 1 < len && top[child].value < top[child + 1].value)
  75.                {
  76.                     child = child + 1; //如果右孩子大,令child等于右孩子的索引
  77.                }

  78.                if(top[child].value > top[i].value)
  79.                {
  80.                     this->swap(top[i], top[child]); //子节点的值大于父节点, 交换父子节点
  81.                     i = child;//以子节点为重新调整的起点!
  82.                }
  83.                else
  84.                {
  85.                break;
  86.                }
  87.           }
  88.      }
  89.      void nodeArrSort(T top[], int topN);
  90.      void nodeFilter(T *head, T top[], int topN, int groupId);
  91.      void nodePrint(T *head);
  92. public:
  93.      T head;
  94.      BAIDU::swap_p<T> swap;
  95. };

  96. #endif

  97.  
  98. /*
  99. file: node.cpp
  100. author: hl
  101. date: 2012-08-07
  102. */
  103. #include <iostream>
  104. #include <assert.h>
  105. #include "node.h"
  106. using namespace std;

  107. template <typename T>
  108. void NodeOperate<T>::nodeInitial(T *head)
  109. {
  110.      head->value = 0;
  111.      head->group = 0;
  112.      head->pnext = NULL;
  113. }

  114. template <typename T>
  115. void NodeOperate<T>::nodeInsert(T *head, T& node)
  116. {
  117.      assert (head != NULL);
  118.      T *p = head;
  119.      T *pre = head;
  120.      while(p)
  121.      {
  122.           pre = p;
  123.           p = p->pnext;
  124.      }
  125.      pre->pnext = &node;
  126.      node.pnext = NULL;
  127. }

  128. template <typename T>
  129. void NodeOperate<T>::nodeCreate(T *head, T arr[], int nodeNumber)
  130. {
  131.      assert (head != NULL);
  132.      for (int i = 1, j = 0; i < nodeNumber; ++i, ++j)
  133.      {
  134.           arr[j].group = (i%10);
  135.           arr[j].value = i;
  136.           this->nodeInsert(head, arr[j]);
  137.      }
  138. }

  139. template <typename T>
  140. void NodeOperate<T>::nodeArrSort(T top[], int topN)
  141. {
  142.      //将数组调整为最大堆
  143.      for(int i = topN / 2; i >= 0; i--)
  144.      {
  145.                this->heapadjust(top, i, topN);
  146.      }

  147.      //不断缩小无序区
  148.      for(int j = topN - 1; j > 0; j--)
  149.      {
  150.           this->swap(top[0], top[j]);
  151.           this->heapadjust(top, 0, j) ;
  152.      }
  153. }

  154. template <typename T>
  155. void NodeOperate<T>::nodeFilter(T *head, T top[], int topN, int groupId)
  156. {
  157.      assert (head != NULL);
  158.      T *p = head;
  159.      int flag = 1;
  160.      int i = 0;
  161.      do
  162.      {
  163.           if (groupId == p->group && flag)
  164.           {
  165.                top[i] = *p;
  166.                if (9 == i)
  167.                {
  168.                     flag = 0;
  169.                     break;
  170.                }
  171.                i++;
  172.           }
  173.      }while(p = p->pnext);
  174.      //比较之前先排序top[]数组(从小到大)
  175.      this->nodeArrSort(top, topN);
  176.      //开始做比较, p之前已经存在,然后到i == 9以后就break, 因此只需要判断下一个是否存在,存在则继续比较;
  177.      while(p = p->pnext)
  178.      {
  179.           if (p->group == groupId)
  180.           {
  181.                if (p->value > top[0].value)
  182.                {
  183.                     top[0].value = p->value;
  184.                     //重新排序top[]数组(从小到大)
  185.                     this->nodeArrSort(top, topN);
  186.                }
  187.           }
  188.      }
  189. }

  190. template <typename T>
  191. void NodeOperate<T>::nodePrint(T *head)
  192. {
  193.      assert (head != NULL);
  194.      T *p = head;
  195.      while(p)
  196.      {
  197.           cout << "group id is " << p->group;
  198.           cout << " value is " << p->value << endl;
  199.           p = p->pnext;
  200.      }
  201. }
  202. /*
  203. file: main.cpp
  204. author: hl
  205. date: 2012-08-07
  206. */
  207. #include <iostream>
  208. #include "node.cpp" //for template
  209. #include "node.h"

  210. using namespace std;

  211. #define RMD(a, b) (a/b) //求余数宏

  212. //辅助打印结构体数组
  213. void printArr(node_t nd[], int num)
  214. {
  215.      for (int i = 0; i < num; ++i)
  216.           cout << nd[i].group << " " << nd[i].value << endl;
  217. }

  218. int main(int argc, char** argv)
  219. {
  220.      /*1st宏替换*/
  221. #if 0
  222.      cout << RMD(2 + 4, 2) << endl; //答案是4? Answer-->2 + 4/2;
  223.      cout << RMD((2 + 4), 2) << endl; //答案是3? Answer-->(2+4)/2;
  224. #endif

  225.      /*2nd单向链表排序输出Top10*/
  226. #if 0
  227.      cmp cmp_t;
  228.      cout << (cmp_t(3, 2) ? (1) : (2)) << endl;
  229.      int a = 4;
  230.      int b = 5;
  231.      cout << "a is " << a << endl << "b is " << b << endl;
  232.      new cmp(a, b);
  233.      cout << "a is " << a << endl << "b is " << b << endl;
  234. #endif

  235.      /*3td*/
  236.      NodeOperate<node_t> no;
  237.      no.nodeInitial(&no.head);
  238.      //no.nodePrint(&no.head);
  239.      /*
  240.      node_t no_t1;
  241.      no_t1.group = 1;
  242.      no_t1.value = 1;
  243.      node_t no_t2;
  244.      no_t2.group = 2;
  245.      no_t2.value = 2;
  246.      //no_t1.pnext = NULL; //如果你没有初始化,并且Inser函数定义方式是void nodeInsert(T *head, T node)
  247.                                 //而不是引用,那么打印的过程则是无法预料的;因为在此时传参方式下函数内部进行node.pnext = NULL;是无效的!
  248.      no.nodeInsert(&no.head, no_t1);
  249.      no.nodeInsert(&no.head, no_t2);
  250.      */
  251.      /*
  252.      struct node_b<int, int> node_b; //使用带模版的节点,看起来也不错;
  253.      node_b.group = 1;
  254.      node_b.value = 1;
  255.      node_b.next = NULL;
  256.      */

  257.      node_t arr[10000]; //其实应该用指针数组比较好;
  258.      //One:构造
  259.      no.nodeCreate(&no.head, arr, 10000);
  260.      //no.nodePrint(&no.head);
  261.      /*Two:筛选出每组Top10 思路:
  262.      * 取出group为0的前10个数,然后排序(从小到大),
  263.      * 然后对后面的group为0的数与新排序的最小的数(就是第一个数)比较,
  264.      * 如果小于就继续往后找,否则替换第一个,然后重新排序(排序如果要求高性能,要用最快的排序方式)
  265.      */
  266.      node_t top[10];
  267.      no.nodeFilter(&no.head, top, 10, 0);
  268.      printArr(top, 10);

  269.      system("pause");
  270.      return 0;
  271. }
我运行了还行,没报错,唉,对了,忘记了是不是还需要释放内存啊,如果可以改进的话我想尝试下shared_ptr“智能指针”,GoGo Study!
阅读(2206) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~