转自 http://www.cnblogs.com/xnwyd/archive/2010/04/28/1723151.html
链表是数据结构的重要内容,在计算机程序中应用广泛,同时也是各公司笔试题目的重点。
以下简单实现了链表的一些操作,包括创建、增加节点、删除节点、单链表逆置、合并有序链表等。
一、链表创建
链表主要有三种形式,包括单链表、双链表和循环链表。
单链表每个节点只包含一个后驱指针,双链表节点同时包含一个前驱指针和一个后驱指针,循环链表的尾节点的后驱指向头节点。
代码如下:
/* 单链表节点结构 */
typedef struct NodeType
{
char elem;
NodeType * next;
}Node;
/* 双链表节点结构 */
typedef struct DNodeType
{
char elem;
DNodeType * next;
DNodeType * prev;
}DNode;
创建单链表
/*
创建链表
*/
Node
*
CreateList(Node
*
head)
{
if
(NULL
==
head)
//
分配头节点空间
head
=
(Node
*
)malloc(
sizeof
(Node)),
head
->
next
=
NULL;
Node
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(Node
*
) malloc (
sizeof
(Node) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
return
head;
}
创建双链表
/*
创建双链表
*/
DNode
*
DoubleList(DNode
*
head)
{
if
(NULL
==
head)
//
分配头节点空间
head
=
(DNode
*
)malloc(
sizeof
(DNode)) , head
->
prev
=
NULL , head
->
next
=
NULL;
DNode
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(DNode
*
) malloc (
sizeof
(DNode) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
temp
->
prev
=
current;
/*
新节点的前驱指向当前节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
return
head;
}
创建循环链表
/*
创建循环链表
*/
Node
*
CycleList(Node
*
head)
{
if
(NULL
==
head)
/*
分配头节点空间
*/
head
=
(Node
*
)malloc(
sizeof
(Node)),head
->
next
=
NULL;
Node
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(Node
*
) malloc (
sizeof
(Node) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
current
->
next
=
head;
/*
尾节点指向头节点
*/
return
head;
}
二、链表操作
包括单链表的增加节点、删除节点、输出链表等
添加节点
/*
插入节点
*/
Node
*
InsertNode(Node
*
head ,
char
elem)
{
if
( NULL
==
head
||
NULL
==
elem )
return
head;
Node
*
current
=
head
->
next;
/*
当前节点
*/
Node
*
prev
=
head;
/*
前驱节点
*/
Node
*
temp;
/*
过渡节点
*/
while
(current)
/*
移动至尾节点
*/
{
prev
=
current;
current
=
current
->
next;
}
temp
=
(Node
*
) malloc(
sizeof
(Node) );
temp
->
elem
=
elem;
temp
->
next
=
NULL;
prev
->
next
=
temp;
/*
尾节点的后驱指向新节点
*/
return
head;
}
添加节点
/*
插入节点
*/
Node
*
InsertNode(Node
*
head ,
char
elem)
{
if
( NULL
==
head
||
NULL
==
elem )
return
head;
Node
*
current
=
head
->
next;
/*
当前节点
*/
Node
*
prev
=
head;
/*
前驱节点
*/
Node
*
temp;
/*
过渡节点
*/
while
(current)
/*
移动至尾节点
*/
{
prev
=
current;
current
=
current
->
next;
}
temp
=
(Node
*
) malloc(
sizeof
(Node) );
temp
->
elem
=
elem;
temp
->
next
=
NULL;
prev
->
next
=
temp;
/*
尾节点的后驱指向新节点
*/
return
head;
}
删除节点
/*
删除节点
*/
Node
*
DeleteNode(Node
*
head,
char
elem)
{
if
(NULL
==
head
||
NULL
==
elem)
return
head;
if
(NULL
==
head
->
next)
return
head;
Node
*
prev,
*
current;
prev
=
head;
current
=
head
->
next;
while
(current)
{
if
(current
->
elem
==
elem)
/*
匹配节点元素
*/
{
prev
->
next
=
current
->
next;
/*
前驱节点的后驱指向当前节点的下一个节点
*/
free(current);
/*
释放当前节点
*/
return
head;
}
prev
=
current;
current
=
current
->
next;
/*
移动至下一个节点
*/
}
return
head;
}
输出链表
/*
输出链表
*/
void
PrintList(Node
*
head)
{
Node
*
current
=
head
->
next;
cout
<<
"
/n List are:
"
;
while
(NULL
!=
current)
{
if
(NULL
!=
current
->
elem)
cout
<<
setw(
5
)
<<
current
->
elem;
current
=
current
->
next;
}
cout
<<
"
/n
"
;
}
三、单链表逆置
单链表逆置在各公司的笔试题中比较常见,以下是其中一种实现。
算法描述:将链表中每一个节点插入到头结点之后。
代码如下:
单链表逆置
/*
单链表逆置
*/
Node
*
ReverseList(Node
*
head)
{
if
(NULL
==
head)
return
head;
if
(NULL
==
head
->
next)
return
head;
if
(NULL
==
head
->
next
->
next)
return
head;
Node
*
curr
=
head
->
next;
/*
当前节点
*/
head
->
next
=
NULL;
Node
*
temp;
while
(curr)
{
temp
=
curr
->
next;
/*
暂存下一个节点
*/
/*
把当前节点插入到head节点后
*/
curr
->
next
=
head
->
next;
head
->
next
=
curr;
curr
=
temp;
/*
移动至下一个节点
*/
}
return
head;
}
四、求单链表中间节点
在笔试题中比较常见,通常题目描述是:给出一个单链表,不知道节点N的值,怎样只遍历一次就可以求出中间节点。
算法描述:设立两个指针p1,p2,p1每次移动1个节点位置,p2每次移动2个节点位置,当p2移动到尾节点时,p1指向中间节点。
代码如下:
求中间节点
/*
求中间节点
*/
Node
*
MiddleNode(Node
*
head)
{
if
(NULL
==
head)
return
head;
if
(NULL
==
head
->
next)
return
head
->
next;
Node
*
p1,
*
p2;
p1
=
head;
p2
=
head;
while
(p2
->
next)
{
/*
p2节点移动2个节点位置
*/
p2
=
p2
->
next;
if
(p2
->
next)
/*
判断p2后驱节点是否存在,存在则再移动一次
*/
p2
=
p2
->
next;
/*
p1节点移动1个节点位置
*/
p1
=
p1
->
next;
}
return
p1;
}
求中间节点
/*
求中间节点
*/
Node
*
MiddleNode(Node
*
head)
{
if
(NULL
==
head)
return
head;
if
(NULL
==
head
->
next)
return
head
->
next;
Node
*
p1,
*
p2;
p1
=
head;
p2
=
head;
while
(p2
->
next)
{
/*
p2节点移动2个节点位置
*/
p2
=
p2
->
next;
if
(p2
->
next)
/*
判断p2后驱节点是否存在,存在则再移动一次
*/
p2
=
p2
->
next;
/*
p1节点移动1个节点位置
*/
p1
=
p1
->
next;
}
return
p1;
}
五、合并有序单链表
问题描述:合并2个有序单链表,合并后的链表也是排好序的。
算法描述:对链表A中的每一个节点元素,查找其在链表B中的插入位置,并在B中插入该元素。
代码如下:
合并有序单链表
/*
合并有序单链表
*/
Node
*
MergeList(Node
*
h1,Node
*
h2)
{
if
(NULL
==
h1
||
NULL
==
h2)
return
h1;
if
(NULL
==
h1
->
next )
return
h2;
if
(NULL
==
h2
->
next)
return
h1;
Node
*
curr1,
*
curr2,
*
prev1,
*
temp;
prev1
=
h1;
/*
链表1的前驱节点
*/
curr1
=
h1
->
next;
/*
链表1的当前节点
*/
curr2
=
h2
->
next;
/*
链表2的当前节点
*/
temp
=
h2;
while
(curr2)
{
while
(curr1
&&
curr1
->
elem
<
curr2
->
elem)
/*
链表1指针移动至大或等于链表2当前元素的位置
*/
prev1
=
curr1,curr1
=
curr1
->
next;
/*
在链表1中插入链表2的当前元素
*/
temp
=
curr2
->
next;
/*
暂存链表2的下一个节点
*/
prev1
->
next
=
curr2;
curr2
->
next
=
curr1;
/*
链表1移动至新节点
*/
curr1
=
curr2;
/*
链表2移动至下一个节点
*/
curr2
=
temp;
}
return
h1;
}
六、判断链表是否有环
判断链表是否有环即是判断链表是否为循环链表,算法较为简单,一次遍历判断尾指针是否指向头指针即可。
代码如下:
判断链表是否有环
/*
判断链表是否有环(循环链表)
*/
bool
IsCycleList(Node
*
head)
{
if
(NULL
==
head)
return
false
;
if
(NULL
==
head
->
next)
return
false
;
Node
*
current
=
head
->
next;
while
(current)
{
if
(head
==
current
->
next)
return
true
;
current
=
current
->
next;
}
return
false
;
}
七、总结
以上实现了链表的一些常见操作,源文件LinkList.cpp全部代码如下:
LinkList.cpp
/*
* 作者: 达闻东
* 修改日期: 2010-04-28 17:10
* 描述: 实现链表的常见操作
*
*/
#include
<
iostream
>
#include
<
iomanip
>
using
namespace
std;
/*
单链表节点结构
*/
typedef
struct
NodeType
{
char
elem;
NodeType
*
next;
}Node;
/*
双链表节点结构
*/
typedef
struct
DNodeType
{
char
elem;
DNodeType
*
next;
DNodeType
*
prev;
}DNode;
/*
=============================================================================
*/
/*
创建链表
*/
Node
*
CreateList(Node
*
head)
{
if
(NULL
==
head)
//
分配头节点空间
head
=
(Node
*
)malloc(
sizeof
(Node)),
head
->
next
=
NULL;
Node
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(Node
*
) malloc (
sizeof
(Node) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
return
head;
}
/*
=============================================================================
*/
/*
输出链表
*/
void
PrintList(Node
*
head)
{
Node
*
current
=
head
->
next;
cout
<<
"
/n List are:
"
;
while
(NULL
!=
current)
{
if
(NULL
!=
current
->
elem)
cout
<<
setw(
5
)
<<
current
->
elem;
current
=
current
->
next;
}
cout
<<
"
/n
"
;
}
/*
=============================================================================
*/
/*
插入节点
*/
Node
*
InsertNode(Node
*
head ,
char
elem)
{
if
( NULL
==
head
||
NULL
==
elem )
return
head;
Node
*
current
=
head
->
next;
/*
当前节点
*/
Node
*
prev
=
head;
/*
前驱节点
*/
Node
*
temp;
/*
过渡节点
*/
while
(current)
/*
移动至尾节点
*/
{
prev
=
current;
current
=
current
->
next;
}
temp
=
(Node
*
) malloc(
sizeof
(Node) );
temp
->
elem
=
elem;
temp
->
next
=
NULL;
prev
->
next
=
temp;
/*
尾节点的后驱指向新节点
*/
return
head;
}
/*
=============================================================================
*/
/*
删除节点
*/
Node
*
DeleteNode(Node
*
head,
char
elem)
{
if
(NULL
==
head
||
NULL
==
elem)
return
head;
if
(NULL
==
head
->
next)
return
head;
Node
*
prev,
*
current;
prev
=
head;
current
=
head
->
next;
while
(current)
{
if
(current
->
elem
==
elem)
/*
匹配节点元素
*/
{
prev
->
next
=
current
->
next;
/*
前驱节点的后驱指向当前节点的下一个节点
*/
free(current);
/*
释放当前节点
*/
return
head;
}
prev
=
current;
current
=
current
->
next;
/*
移动至下一个节点
*/
}
return
head;
}
/*
=============================================================================
*/
/*
单链表逆置
*/
Node
*
ReverseList(Node
*
head)
{
if
(NULL
==
head)
return
head;
if
(NULL
==
head
->
next)
return
head;
if
(NULL
==
head
->
next
->
next)
return
head;
Node
*
curr
=
head
->
next;
/*
当前节点
*/
head
->
next
=
NULL;
Node
*
temp;
while
(curr)
{
temp
=
curr
->
next;
/*
暂存下一个节点
*/
/*
把当前节点插入到head节点后
*/
curr
->
next
=
head
->
next;
head
->
next
=
curr;
curr
=
temp;
/*
移动至下一个节点
*/
}
return
head;
}
/*
=============================================================================
*/
/*
求中间节点
*/
Node
*
MiddleNode(Node
*
head)
{
if
(NULL
==
head)
return
head;
if
(NULL
==
head
->
next)
return
head
->
next;
Node
*
p1,
*
p2;
p1
=
head;
p2
=
head;
while
(p2
->
next)
{
/*
p2节点移动2个节点位置
*/
p2
=
p2
->
next;
if
(p2
->
next)
/*
判断p2后驱节点是否存在,存在则再移动一次
*/
p2
=
p2
->
next;
/*
p1节点移动1个节点位置
*/
p1
=
p1
->
next;
}
return
p1;
}
/*
=============================================================================
*/
/*
合并有序单链表
*/
Node
*
MergeList(Node
*
h1,Node
*
h2)
{
if
(NULL
==
h1
||
NULL
==
h2)
return
h1;
if
(NULL
==
h1
->
next )
return
h2;
if
(NULL
==
h2
->
next)
return
h1;
Node
*
curr1,
*
curr2,
*
prev1,
*
temp;
prev1
=
h1;
/*
链表1的前驱节点
*/
curr1
=
h1
->
next;
/*
链表1的当前节点
*/
curr2
=
h2
->
next;
/*
链表2的当前节点
*/
temp
=
h2;
while
(curr2)
{
while
(curr1
&&
curr1
->
elem
<
curr2
->
elem)
/*
链表1指针移动至大或等于链表2当前元素的位置
*/
prev1
=
curr1,curr1
=
curr1
->
next;
/*
在链表1中插入链表2的当前元素
*/
temp
=
curr2
->
next;
/*
暂存链表2的下一个节点
*/
prev1
->
next
=
curr2;
curr2
->
next
=
curr1;
/*
链表1移动至新节点
*/
curr1
=
curr2;
/*
链表2移动至下一个节点
*/
curr2
=
temp;
}
return
h1;
}
/*
=============================================================================
*/
/*
创建双链表
*/
DNode
*
DoubleList(DNode
*
head)
{
if
(NULL
==
head)
//
分配头节点空间
head
=
(DNode
*
)malloc(
sizeof
(DNode)) , head
->
prev
=
NULL , head
->
next
=
NULL;
DNode
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(DNode
*
) malloc (
sizeof
(DNode) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
temp
->
prev
=
current;
/*
新节点的前驱指向当前节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
return
head;
}
/*
=============================================================================
*/
/*
输出双链表
*/
void
PrintDoubleList(DNode
*
head)
{
if
(NULL
==
head)
return
;
DNode
*
p;
p
=
head;
cout
<<
"
/n DoubleList are:
"
;
while
(p
->
next)
{
p
=
p
->
next;
if
(p
->
elem)
cout
<<
setw(
5
)
<<
p
->
elem;
}
cout
<<
"
/n DoubleList are:
"
;
while
(p
->
prev)
{
if
(p
->
elem)
cout
<<
setw(
5
)
<<
p
->
elem;
p
=
p
->
prev;
}
}
/*
=============================================================================
*/
/*
创建循环链表
*/
Node
*
CycleList(Node
*
head)
{
if
(NULL
==
head)
/*
分配头节点空间
*/
head
=
(Node
*
)malloc(
sizeof
(Node)),head
->
next
=
NULL;
Node
*
current
=
head ,
*
temp;
char
ch;
while
(
1
)
{
cout
<<
"
/n input elem:
"
;
cin
>>
ch;
if
(
'
#
'
==
ch)
/*
#结束输入
*/
break
;
temp
=
(Node
*
) malloc (
sizeof
(Node) );
temp
->
elem
=
ch;
temp
->
next
=
NULL;
current
->
next
=
temp;
/*
当前节点的后驱指向新节点
*/
current
=
temp;
/*
当前节点为链表尾节点
*/
}
current
->
next
=
head;
/*
尾节点指向头节点
*/
return
head;
}
/*
=============================================================================
*/
/*
判断链表是否有环(循环链表)
*/
bool
IsCycleList(Node
*
head)
{
if
(NULL
==
head)
return
false
;
if
(NULL
==
head
->
next)
return
false
;
Node
*
current
=
head
->
next;
while
(current)
{
if
(head
==
current
->
next)
return
true
;
current
=
current
->
next;
}
return
false
;
}
int
main()
{
Node
*
head,
*
p;
Node
*
head2,
*
head3;
DNode
*
dHead;
char
ch;
head
=
NULL;
head2
=
NULL;
head3
=
NULL;
dHead
=
NULL;
//
head=(Node*) malloc ( sizeof( Node) );
//
head->next = NULL;
//
创建单链表
head
=
CreateList(head);
PrintList(head);
head2
=
CreateList(head2);
PrintList(head2);
//
插入节点
cout
<<
"
/n input elem to insert:
"
;
cin
>>
ch;
InsertNode(head,ch);
PrintList(head);
//
删除节点
cout
<<
"
/n input elem to delete:
"
;
cin
>>
ch;
DeleteNode(head,ch);
PrintList(head);
//
单链表逆置
head
=
ReverseList(head);
cout
<<
"
/n Reversed !
"
;
PrintList(head);
//
求中间节点
p
=
MiddleNode(head);
cout
<<
"
/n Middle Node is:
"
;
cout
<<
p
->
elem
<<
endl;
//
合并有序单链表
MergeList(head,head2);
cout
<<
"
/n Merged!
"
;
PrintList(head);
//
创建双链表
dHead
=
DoubleList(dHead);
PrintDoubleList(dHead);
/*
创建循环链表并判断是否有环
*/
head3
=
CycleList(head3);
cout
<<
IsCycleList(head3);
return
0
;
}
14万+

被折叠的 条评论
为什么被折叠?



