[数据结构与算法]小甲鱼教程题目_找出未知长度单链表的中间元素

据说是腾讯招聘的题目。。

老实说,我对小甲鱼给出的答案很不以为然,小甲鱼的方法只是循环次数减少了,不见得总的执行次数会少多少。。不知道是不是我对算法的执行效率有误解。。。。。不过我也没有找到更好的办法,贴代码吧。

我的设想:

  n = GetLength_L();  //获得长度  循环N次

  找到第[n/2]元素  // 循环 [N/2]

小甲鱼的解法:

  快慢指针方法

  LNode * search ;

      LNode  *mid;

开始时 search = mid  都指向头指针,然后search每次按两个元素往单链表的后续元素推进,mid每次俺一个元素往单链表的元素推进。当search到达末尾的时候,mid刚好指向中间元素。。。

就好比两个人一起赛跑(跑道长度位置),甲乙两人同时在起点出发,甲的速度是乙的速度的两倍,甲到终点的时候,乙恰好在中间位置。。。。

--code为小甲鱼解法的实现。。

 1 /*******************************************************
 2 * @: Project:    找未知长度单链表的中间元素
 3 * @: File:        link_list.h
 4 * @: Function: 提供单链表操作的数据结构定义及方法声明
 5 * @: History:    2013-10-01 22:37:05
 6 * @: Author:    Alimy
 7 *******************************************************/
 8 
 9 /*******************************************************
10 * @:头文件包含
11 *******************************************************/
12 
13 
14 #ifndef __LINK_LIST_H__
15 #define __LINK_LIST_H__
16 
17 
18 /*******************************************
19 * @: 数据结构定义&一些宏
20 ********************************************/
21 #define ElemType   signed short    int            // 此例子中的数据为有符号短整形,在VC6 中占据16bits
22 #define StatusType    int        //操作状态为int类型
23 #define OK    (StatusType)1
24 #define ERROR (StatusType)0
25 
26 
27 typedef struct LNode{
28     ElemType m_data;              // 数据域
29     struct LNode *p_next;     // 指针域
30 } LNode, *pLinkList;
31 
32 //typedef struct LHead{ //头结点,其实和 LNode的内存结构相似,
33 //    int ElemNumber;  //数据域,可以存储当前线性表的长度,也可以什么也不存储
34 //    struct LNode *p_FirstNode; //指针域指向线性表的第一个元素
35 //}LHead, *pLHead;
36 
37 /*******************************************
38 * @: 外部调用函数声明
39 ********************************************/
40 extern StatusType CreateList_L(pLinkList *pL,int num);//构造num个结点的单链表
41 extern StatusType GetMidNode(pLinkList *pL,ElemType *pe); //找到未知长度链表的 中间元素
42 extern void ClearList_L(pLinkList *pL);    //整表删除
43 extern void DisplayList_L(pLinkList *pL);//输出显示pL指向的链表中的所有元素
44 
45 #endif
link_list.h
  1 /*******************************************************
  2 * @: Project:    找未知长度单链表的中间元素
  3 * @: File:        GetMidNode.c
  4 * @: Function:提供单链表操作相关函数
  5 * @: Version:    2013-10-09 22:09:36
  6 * @: Author:    Alimy
  7 *******************************************************/
  8 
  9 /*******************************************************
 10 * @: 头文件包含 
 11 *******************************************************/
 12 
 13 #include "link_list.h"
 14 #include <stdio.h> 
 15 #include <conio.h>        // int getch(void);
 16 #include <stdlib.h>        // int rand(void);  malloc(); free();
 17 #include <time.h>            // time_t time(time_t *);
 18 
 19 
 20 /*******************************************************
 21 * @: (外部&内部)变量声明及定义
 22 *******************************************************/
 23 
 24 /*******************************************************
 25 * @: (外部&内部)函数声明及定义
 26 *******************************************************/
 27 StatusType CreateList_L(pLinkList *pL,int num);//构造num个结点的单链表
 28 StatusType GetMidNode(pLinkList *pL,ElemType *pe); //找到未知长度链表的 中间元素
 29 void DisplayList_L(pLinkList *pL);//输出显示pL指向的链表中的所有元素
 30 void ClearList_L(pLinkList *pL);    //整表删除
 31 
 32 
 33 
 34 /*******************************************************
 35 * @: 内部函数具体实现
 36 *******************************************************/
 37 
 38 
 39 /*
 40 *@:在堆中构造一个单链表,并逆序插入num个结点(头插法)
 41 *@:返回值 
 42 *@:    构造成功返回OK
 43 *@: 构造失败返回ERROR
 44 **/
 45 StatusType CreateList_L(pLinkList *pL,int num){//构造num个结点的单链表
 46 
 47     LNode*  p_Work = NULL; //工作指针
 48     int idx = 0;
 49     
 50     if(*pL!=NULL){
 51         printf("当前单链表已被初始化,不需要执行Create操作 
");
 52         return ERROR;
 53     }
 54 
 55     *pL = (pLinkList)malloc(sizeof(LNode));
 56     if(*pL == NULL){
 57         printf("在堆中申请头结点失败 
");
 58         return ERROR;        
 59     }
 60     (*pL)->m_data = 0;  // 数据域可以存储当前单链表的长度
 61     (*pL)->p_next = NULL;
 62     
 63     srand(time(0));
 64     for(idx=0;idx<num;idx++){
 65         p_Work = (pLinkList)malloc(sizeof(LNode)); //在堆中申请新的结点
 66         if(p_Work==NULL){
 67             printf("在堆中申请结点出现异常,构造单链表失败  
");
 68             return ERROR;
 69         }
 70         
 71         //p_Work->m_data = 10*s_data[idx%10];//(rand()%(10)); //均为10以内的整数
 72         p_Work->m_data = (rand()%(100))+1; //晕死,每次生产的随机数怎么都一样
 73         p_Work->p_next = (*pL)->p_next;
 74         (*pL)->p_next = p_Work;          //逆序插入,第一个产生为表尾
 75     }
 76     printf("构造含【%d】个元素的单链表成功
",num);
 77     getch();
 78     return OK;
 79 }
 80 /*
 81 *@:在pL指向的未知长度的单链表中找到中间元素,并将中间元素的值赋值给pe指向的内存
 82 *@:返回值
 83 *     找到         -->    返回OK
 84 *            没找到    -->    返回ERROR
 85 */
 86 
 87 StatusType GetMidNode(pLinkList *pL,ElemType *pe){ //找到未知长度链表的 中间元素
 88     LNode * p_search = NULL; //快指针
 89     LNode * p_mid = NULL;        //慢指针
 90     
 91     p_search = p_mid = *pL; // 都指向头结点
 92     
 93     if((*pL)->p_next == NULL){
 94         printf("此单链表为空表,无法执行找到中间元素的操作 
");
 95         return ERROR;
 96     }
 97     if(p_search->p_next->p_next == NULL){
 98         printf("此单链表的元素个数为1
");
 99         *pe = p_search->p_next->m_data;
100         return OK;
101         }
102     
103     while(p_search->p_next!=NULL){
104         if(p_search->p_next->p_next!=NULL){
105             p_mid = p_mid ->p_next;
106             p_search = p_search->p_next->p_next;
107             }    
108             else{
109                 p_search = p_search->p_next;//让while跳出循环
110                 }
111     }
112 
113     *pe = p_mid->m_data;
114     return OK;
115 
116 }
117 
118 
119 /*
120 *@: 输出显示pL指向的单链表所有的元素
121 */
122 void DisplayList_L(pLinkList *pL){ //显示当前所有单链表的长度
123 
124     int idx = 0;
125     LNode* p_Work = NULL;
126 
127     if(*pL==NULL){
128         printf("单链表还未构建,输不出东东 
");
129         return ;
130     }
131     
132     idx = 0;
133     p_Work = (*pL); // 工作指针指向头结点,计数清零
134     if(p_Work->p_next==NULL){
135         printf("当前单链表为空表,没什么东东好显示的 
");
136         return ;
137     }
138     else{
139         while(p_Work->p_next){ //(p_Work->p_next!=NULL)
140             idx++;
141             p_Work = p_Work->p_next;
142             printf("单链表第【%d】个元素的值为【%d】
",idx,p_Work->m_data);
143         }
144         return ;
145     }
146     
147     
148 }
149 
150 
151 /*
152 *@:删除pL指向的单链表的所有结点
153 */
154 
155 void ClearList_L(pLinkList *pL){    //整表删除
156     LNode* p_Work1 = NULL;
157     LNode* p_Work2 = NULL; //工作指针
158     
159     if(*pL == NULL){
160         printf("当前单链表未创建,无法执行整表删除操作 
");
161         return ;
162     }
163     else if((*pL)->p_next == NULL){
164         printf("当前单链表为空表,不需要执行整表删除操作 
");
165         return;
166     }
167     else{
168         p_Work1 = (*pL)->p_next; // 指向第一个结点(如果有的话)
169         while(p_Work1!=NULL){
170             p_Work2 = p_Work1;
171             p_Work1 = p_Work2->p_next;//指向下一个
172             free(p_Work2);
173         }
174 
175     //    (*pL)->p_next = NULL;        // 头结点指向NULL
176         (*pL)->m_data = 0;
177         return ;
178     }
179 }
GetMidNode.c
 1 #include <stdio.h>
 2 #include "link_list.h"
 3 
 4 
 5 
 6 int main(void){
 7     int num = 0;
 8     ElemType e = 0;
 9     pLinkList LinkList_Display = NULL;    
10     printf("请输入你要构建单链表的个数 
");
11     scanf("%d",&num);
12     CreateList_L(&LinkList_Display,num);
13     DisplayList_L(&LinkList_Display);
14     
15     if(OK == GetMidNode(&LinkList_Display,&e)){
16         printf("中间元素的值为 【%d】
",e);
17         }
18         
19     getch();
20     
21     
22     
23     // 打扫堆战场
24     ClearList_L(&LinkList_Display);
25     if(LinkList_Display != NULL)
26         free(LinkList_Display);
27     return OK;
28     
29 }
main.c

  

~不再更新,都不让我写公式,博客园太拉胯了
原文地址:https://www.cnblogs.com/alimy/p/3362006.html