Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1683126
  • 博文数量: 311
  • 博客积分: 7778
  • 博客等级: 少将
  • 技术积分: 4186
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 19:59
个人简介

蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88

文章存档

2012年(3)

2011年(115)

2010年(170)

2009年(23)

分类: C/C++

2010-03-04 15:49:00

这是一个流传很广的面试题:已知一个链表的头结点,结点数未知。请找出链表的中间结点,这里的中间结点的意思是。如果结点数为5个,则中间结点是第3个。如果结点数是6个。则第3,4个任意为中间结点。
 
算法分析:如果一开始就用两次扫描法来(一次计数,第二次找出中间结点),这个算法显得有点简单。一次般大部分解法是要求做两个指针,一个指针在链表移动两步,一个指针在链表移动一步。当移动二步的指针到尾后,移动一步就指针指向就是中间结点。
 
要求一用C语言自写数据结构来实现这一算法:
 

struct node {
  struct node * next;
  int data;
};


struct node * find_mid(struct node * p_first)
{
   struct node * p_node1= p_first;
   struct node * p_node2= p_first;
   
   if(p_node1 == NULL)
      return NULL;
   
   while(1)
   {
      if(p_node1->next == NULL)
         break;
                
         
      if(p_node2->next->next == NULL)
        break;
        
       p_node1 = p_node1->next ;
        
       p_node2 = p_node2->next->next;
                         
   }
   
   return p_node1;
}

在上C++,STL的课程时,我会要求学员用list容器来实现这个算法,(不准使用 .size())这个有一些难度。
因为STL的iterator只知道到没有到尾,而没办法判断是否越界。如果使用iterator+2,很有可能越界,而无未能判断结束(实测程序正是如此),另外list没有重载+和+=。不能用加2。
 
所以这个题变得有点象脑筋急转弯了,怎么利用现有方法实现算法?我提供一个思路,就是把加2步算法,拆成两步,每一步都要判断it !=list.end()即可。
 
下面是一个同学提供比较好的算法.
 
 
 

#include <iostream>
using namespace std;

#include <list>


typedef list<int> int_list;


int find_mid(int_list & list)
{
  int_list::iterator it1,it2;
  
  for(it1=it2=list.begin(); it2!=list.end() && ++it2 != list.end() ; it2++,it1++);
  
  return *it1;
  
}


int main()
{
  int_list list ;
  
  for(int i=0 ; i < 100 ; i++)
     list.push_back(i);
     
 cout << find_mid(list) <<endl;
}



阅读(1052) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~