//原文链接:http://www.cnblogs.com/xnwyd/
/*
* 作者: 达闻东
* 修改日期: 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;
}
链表逆序
设链表节点为
1. typedef struct tagListNode{
2. int data;
3. struct tagListNode* next;
4. }ListNode, *List;
要求将一带链表头List head的单向链表逆序。
分析:
1). 若链表为空或只有一个元素,则直接返回;
2). 设置两个前后相邻的指针p,q. 将p所指向的节点作为q指向节点的后继;
3). 重复2),直到q为空
4). 调整链表头和链表尾
示例:以逆序A->B->C->D为例,图示如下
实现及测试代码如下:
1. #include <stdio.h>
2. #include <stdlib.h>
3.
4. typedef struct tagListNode{
5. int data;
6. struct tagListNode* next;
7. }ListNode, *List;
8.
9. void PrintList(List head);
10. List ReverseList(List head);
11.
12. int main()
13. {
14. //分配链表头结点
15. ListNode *head;
16. head = (ListNode*)malloc(sizeof(ListNode));
17. head->next = NULL;
18. head->data = -1;
19.
20. //将[1,10]加入链表
21. int i;
22. ListNode *p, *q;
23. p = head;
24. for(i = 1; i <= 10; i++)
25. {
26. q = (ListNode *)malloc(sizeof(ListNode));
27. q->data = i;
28. q->next = NULL;
29. p->next = q;
30. p = q;
31. }
32.
33. PrintList(head); /*输出原始链表*/
34. head = ReverseList(head); /*逆序链表*/
35. PrintList(head); /*输出逆序后的链表*/
36. return 0;
37. }
38.
39. List ReverseList(List head)
40. {
41. if(head->next == NULL || head->next->next == NULL)
42. {
43. return head; /*链表为空或只有一个元素则直接返回*/
44. }
45.
46. ListNode *t = NULL,
47. *p = head->next,
48. *q = head->next->next;
49. while(q != NULL)
50. {
51. t = q->next;
52. q->next = p;
53. p = q;
54. q = t;
55. }
56.
57. /*此时q指向原始链表最后一个元素,也是逆转后的链表的表头元素*/
58. head->next->next = NULL; /*设置链表尾*/
59. head->next = p; /*调整链表头*/
60. return head;
61. }
62.
63. void PrintList(List head)
64. {
65. ListNode* p = head->next;
66. while(p != NULL)
67. {
68. printf("%d ", p->data);
69. p = p->next;
70. }
71. printf("/n");
72. }