链表的三个经典问题
2012-04-26 22:46
399 查看
问题1:给定一个单项链表,设计一个时间优化并且时间优化的算法,找出该链表的倒数第m个元素。当m=0时,返回链表的最后一个元素。
[分析:用双指针来实现,两指针间隔m。同步移动两指针,当前一个指针为该链表tail时,后一个指针就为要找的元素]
Element * FindMToLastElement( Element * head, int m)
{
Element * current, * mBehind;
int i;
current = head;
for( i = 0; i < m; i++)
{
if(current->next)
{
current = current->next;
}
else
{
return NULL;
}
}
mBehind = head;
while(current->next)
{
current = current->next;
mBehind = mBehind->next;
}
return mBehind;
}
问题2:从一个标准的双向链表开始。假定除了next指针和previous指针之外,每个元素保存了一个child指针,它可能指向一个独立的双向链表,也可能为空。这些子链表又可能有一个或多个子链表,如此下去,得到了一个多层次的数据结构。将这个链表展平,使得所有节点都出现在一个一层的双向链表中。每个节点定义如下:
typedef struct Node{
struct Node * next;
struct Node * prev;
struct Node * child;
int value;
}Node;
[分析:从第一层链表头开始遍历链表,如果有第二层链表,则将其放到第一层链表尾。这样其实第一层链表尾一直在往后移动,原来的第一层在遍历完后就可以直接遍历第二层了,依此类推就可以完成题目要求,前提要有一个指向尾指针的指针]
void FlattenList( Node * head, Node ** tail)
{
Node * curNode = head;
while( curNode )
{
if(curNode->child)
{
Append(curNode->child, tail);
}
curNode = curNode->next;
}
}
void Append( Node * child, Node ** tail)
{
Node * curNode;
(*tail)->next = child;
child-prev = *tail;
for(curNode = child; curNode->next; curNode = curNode->next)
{
}
*tail = curNode;
}
问题3:编写一个函数,接受链表的头指针作为参数,确定该链表是循环的还是非循环的。如果链表是非循环的,函数返回false;如果是循环的,函数返回true。不能以任何方式修改该链表。
[分析:用双指针实现,一个用step=1前进,一个用step=2前进。看两个指针是否能相遇]
bool DetermineTermination( Node * head)
{
Node * fast, * slow;
fast = slow = head;
while(true)
{
if(!fast || !fast->next)
{
return false;
}
else if(fast == slow || fast->next == slow)
{
return true;
}
else
{
slow = slow->next;
fast = fast->next->next;
}
}
}
[分析:用双指针来实现,两指针间隔m。同步移动两指针,当前一个指针为该链表tail时,后一个指针就为要找的元素]
Element * FindMToLastElement( Element * head, int m)
{
Element * current, * mBehind;
int i;
current = head;
for( i = 0; i < m; i++)
{
if(current->next)
{
current = current->next;
}
else
{
return NULL;
}
}
mBehind = head;
while(current->next)
{
current = current->next;
mBehind = mBehind->next;
}
return mBehind;
}
问题2:从一个标准的双向链表开始。假定除了next指针和previous指针之外,每个元素保存了一个child指针,它可能指向一个独立的双向链表,也可能为空。这些子链表又可能有一个或多个子链表,如此下去,得到了一个多层次的数据结构。将这个链表展平,使得所有节点都出现在一个一层的双向链表中。每个节点定义如下:
typedef struct Node{
struct Node * next;
struct Node * prev;
struct Node * child;
int value;
}Node;
[分析:从第一层链表头开始遍历链表,如果有第二层链表,则将其放到第一层链表尾。这样其实第一层链表尾一直在往后移动,原来的第一层在遍历完后就可以直接遍历第二层了,依此类推就可以完成题目要求,前提要有一个指向尾指针的指针]
void FlattenList( Node * head, Node ** tail)
{
Node * curNode = head;
while( curNode )
{
if(curNode->child)
{
Append(curNode->child, tail);
}
curNode = curNode->next;
}
}
void Append( Node * child, Node ** tail)
{
Node * curNode;
(*tail)->next = child;
child-prev = *tail;
for(curNode = child; curNode->next; curNode = curNode->next)
{
}
*tail = curNode;
}
问题3:编写一个函数,接受链表的头指针作为参数,确定该链表是循环的还是非循环的。如果链表是非循环的,函数返回false;如果是循环的,函数返回true。不能以任何方式修改该链表。
[分析:用双指针实现,一个用step=1前进,一个用step=2前进。看两个指针是否能相遇]
bool DetermineTermination( Node * head)
{
Node * fast, * slow;
fast = slow = head;
while(true)
{
if(!fast || !fast->next)
{
return false;
}
else if(fast == slow || fast->next == slow)
{
return true;
}
else
{
slow = slow->next;
fast = fast->next->next;
}
}
}
相关文章推荐
- 链表的三个经典问题
- 单链表中的一些经典问题--约瑟夫环,逆序,查找,复杂链表复制,链表带环问题
- 转帖:关于链表操作不得不看的经典问题
- 【经典问题】判断单链表是否存在环,判断两个链表是否相交问题详解
- 单链表经典题集之带环问题
- 单链表中一些经典的问题-->约瑟夫环,链表逆序,查找链表结点...(上)
- 数列问题 , 经典的链表操作
- 经典面试题:链表的相交与环问题
- 链表的几个经典问题-读《程序员面试攻略》
- 链表经典问题汇总
- 链表经典问题汇总
- 数列问题 , 经典的链表操作
- 单链表的三个典型问题
- 链表的经典问题
- 经典面试题:链表的相交与环问题
- 进程同步之信号量机制(pv操作)及三个经典同步问题
- NYOJ21 三个水杯 (经典问题 bfs)
- 经典面试题:链表的相交与环问题
- 关于链表的一些经典问题以及相关面试题
- 链表经典问题——猴子选大王