织梦CMS - 轻松建站从此开始!

罗索

链表的常见操作

jackyhwei 发布于 2011-09-30 16:04 点击:次 
链表是数据结构的重要内容,在计算机程序中应用广泛,同时也是各公司笔试题目的重点。以下简单实现了链表的一些操作,包括创建、增加节点、删除节点、单链表逆置、合并有序链表等。
TAG:

链表是数据结构的重要内容,在计算机程序中应用广泛,同时也是各公司笔试题目的重点。

以下简单实现了链表的一些操作,包括创建、增加节点、删除节点、单链表逆置、合并有序链表等。

一、链表创建

链表主要有三种形式,包括单链表、双链表和循环链表

单链表每个节点只包含一个后驱指针,双链表节点同时包含一个前驱指针和一个后驱指针,循环链表的尾节点的后驱指向头节点。

代码如下:

  1. /*单链表节点结构*/ 
  2. typedef structNodeType 
  3.   char elem; 
  4.   NodeType*next; 
  5. }Node; 
  6.  
  7. /*双链表节点结构*/ 
  8. typedef structDNodeType 
  9. char elem; 
  10.  DNodeType*next; 
  11.  DNodeType*prev; 
  12. }DNode; 
  13.  
  14. /* 
  15. 创建链表 
  16. */ 
  17. Node* CreateList(Node*head) 
  18. if(NULL== head)//分配头节点空间 
  19.  head=(Node*)malloc(sizeof(Node)), 
  20.  head->next=NULL; 
  21.  
  22.  Node*current=head ,*temp; 
  23. char ch; 
  24.  
  25. while(1) 
  26.  { 
  27.  cout<<"\n input elem:"
  28.  cin>>ch; 
  29. if('#' == ch)/*#结束输入*/ 
  30. break
  31.  temp=(Node*) malloc (sizeof(Node) ); 
  32.  temp->elem=ch; 
  33.  temp->next=NULL; 
  34.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  35.  current=temp;/*当前节点为链表尾节点*/ 
  36.  
  37.  } 
  38.  
  39. return head; 
  40.  
  41.   
  42.  
  43. /*创建双链表*/ 
  44. DNode* DoubleList(DNode*head) 
  45. if(NULL== head)//分配头节点空间 
  46.  head=(DNode*)malloc(sizeof(DNode)) , head->prev=NULL ,head->next=NULL; 
  47.  
  48.  DNode*current=head ,*temp; 
  49. char ch; 
  50.  
  51. while(1) 
  52.  { 
  53.  cout<<"\n input elem:"
  54.  cin>>ch; 
  55. if('#' == ch)/*#结束输入*/ 
  56. break
  57.  temp=(DNode*) malloc (sizeof(DNode) ); 
  58.  temp->elem=ch; 
  59.  temp->next=NULL; 
  60.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  61.  temp->prev=current;/*新节点的前驱指向当前节点*/ 
  62.  current=temp;/*当前节点为链表尾节点*/ 
  63.  
  64.  } 
  65.  
  66. return head; 
  67.  
  68.   
  69.  
  70. /*创建循环链表*/ 
  71. Node* CycleList(Node*head) 
  72. if(NULL== head)/*分配头节点空间*/ 
  73.  head=(Node*)malloc(sizeof(Node)),head->next=NULL; 
  74.  
  75.  Node*current=head ,*temp; 
  76. char ch; 
  77.  
  78. while(1) 
  79.  { 
  80.  cout<<"\n input elem:"
  81.  cin>>ch; 
  82. if('#' == ch)/*#结束输入*/ 
  83. break
  84.  temp=(Node*) malloc (sizeof(Node) ); 
  85.  temp->elem=ch; 
  86.  temp->next=NULL; 
  87.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  88.  current=temp;/*当前节点为链表尾节点*/ 
  89.  
  90.  } 
  91.  current->next=head;/*尾节点指向头节点*/ 
  92. return head; 

二、链表操作

包括单链表的增加节点、删除节点、输出链表等

  1. /*在尾部插入节点#add 可以直接在指定参数节点插入*/ 
  2. Node*InsertNode(Node*head ,char elem) 
  3. if( NULL== head|| NULL== elem ) 
  4. return head; 
  5.  
  6.  Node*current=head->next;/*当前节点*/ 
  7.  Node*prev=head;/*前驱节点*/ 
  8.  Node*temp;/*过渡节点*/ 
  9.  
  10. while(current)/*移动至尾节点*/ 
  11.  { 
  12.  prev=current; 
  13.  current=current->next; 
  14.  } 
  15.  
  16.  temp=(Node*)malloc(sizeof(Node)); 
  17.  temp->elem=elem; 
  18.  temp->next=NULL; 
  19.  prev->next=temp;/*尾节点的后驱指向新节点*/ 
  20.  
  21. return head; 
  22.  
  23. /*删除节点*/ 
  24. Node*DeleteNode(Node*head,char elem) 
  25. if(NULL== head|| NULL== elem) 
  26. return head; 
  27. if(NULL== head->next) 
  28. return head; 
  29.  
  30.  Node*prev,*current; 
  31.  prev=head; 
  32.  current=head->next; 
  33.  
  34. while(current) 
  35.  { 
  36. if(current->elem== elem)/*匹配节点元素*/ 
  37.  { 
  38.  prev->next=current->next;/*前驱节点的后驱指向当前节点的下一个节点*/ 
  39.  free(current);/*释放当前节点*/ 
  40. return head; 
  41.  } 
  42.  prev=current; 
  43.  current=current->next;/*移动至下一个节点*/ 
  44.  } 
  45.  
  46. return head; 
  47.  
  48. /*输出链表*/ 
  49. void PrintList(Node*head) 
  50.  Node* current=head->next; 
  51.  cout<<"\n List are:"
  52. while(NULL!= current) 
  53.  { 
  54. if(NULL!= current->elem) 
  55.  cout<<setw(5)<<current->elem; 
  56.  current=current->next; 
  57.  } 
  58.  
  59.  cout<<"\n"

三、单链表逆置

单链表逆置在各公司的笔试题中比较常见,以下是其中一种实现。

算法描述:将链表中每一个节点插入到头结点之后。

代码如下:

  1. /*单链表逆置*/ 
  2. Node*ReverseList(Node*head) 
  3. if(NULL== head) 
  4. return head; 
  5. if(NULL== head->next) 
  6. return head; 
  7. if(NULL== head->next->next) 
  8. return head; 
  9.  
  10.  Node*curr=head->next;/*当前节点*/ 
  11.  head->next=NULL; 
  12.  Node*temp; 
  13.  
  14. while(curr) 
  15.  { 
  16.  temp=curr->next;/*暂存下一个节点*/ 
  17. /*把当前节点插入到head节点后*/ 
  18.  curr->next=head->next; 
  19.  head->next=curr; 
  20.  
  21.  curr=temp;/*移动至下一个节点*/ 
  22.  } 
  23.  
  24. return head; 

四、求单链表中间节点

在笔试题中比较常见,通常题目描述是:给出一个单链表,不知道节点N的值,怎样只遍历一次就可以求出中间节点。

算法描述:设立两个指针p1,p2,p1每次移动1个节点位置,p2每次移动2个节点位置,当p2移动到尾节点时,p1指向中间节点。

代码如下:

  1. /*求中间节点*/ 
  2. Node* MiddleNode(Node*head) 
  3. if(NULL== head) 
  4. return head; 
  5. if(NULL== head->next) 
  6. return head->next; 
  7.  
  8.  Node*p1,*p2; 
  9.  p1=head; 
  10.  p2=head; 
  11.  
  12. while(p2->next) 
  13.  { 
  14. /*p2节点移动2个节点位置*/ 
  15.  p2=p2->next; 
  16. if(p2->next)/*判断p2后驱节点是否存在,存在则再移动一次*/ 
  17.  p2=p2->next; 
  18. /*p1节点移动1个节点位置*/ 
  19.  p1=p1->next; 
  20.  
  21.  } 
  22. return p1; 

五、合并有序单链表

问题描述:合并2个有序单链表,合并后的链表也是排好序的。

算法描述:对链表A中的每一个节点元素,查找其在链表B中的插入位置,并在B中插入该元素。

代码如下:

  1. /*合并有序单链表*/ 
  2. Node* MergeList(Node*h1,Node* h2) 
  3. if(NULL== h1|| NULL== h2) 
  4. return h1; 
  5. if(NULL== h1->next ) 
  6. return h2; 
  7. if(NULL== h2->next) 
  8. return h1; 
  9.  
  10.  Node* curr1,*curr2,*prev1,*temp; 
  11.  prev1=h1;/*链表1的前驱节点*/ 
  12.  curr1=h1->next;/*链表1的当前节点*/ 
  13.  curr2=h2->next;/*链表2的当前节点*/ 
  14.  temp=h2; 
  15. while(curr2) 
  16.  { 
  17. while(curr1&&curr1->elem< curr2->elem)/*链表1指针移动至大或等于链表2当前元素的位置*/ 
  18.  prev1=curr1,curr1=curr1->next; 
  19.  
  20. /*在链表1中插入链表2的当前元素*/ 
  21.  temp=curr2->next;/*暂存链表2的下一个节点*/ 
  22.  prev1->next=curr2; 
  23.  curr2->next=curr1; 
  24.  
  25. /*链表1移动至新节点*/ 
  26.  curr1=curr2; 
  27. /*链表2移动至下一个节点*/ 
  28.  curr2=temp; 
  29.  } 
  30.  
  31. return h1; 

六、判断链表是否有环

判断链表是否有环即是判断链表是否为循环链表,算法较为简单,一次遍历判断尾指针是否指向头指针即可。代码如下:

  1. /*判断链表是否有环(循环链表)*/ 
  2. bool IsCycleList(Node*head) 
  3. if(NULL== head) 
  4. return false
  5. if(NULL== head->next) 
  6. return false
  7.  Node*current=head->next; 
  8. while(current) 
  9.  { 
  10. if(head== current->next) 
  11. return true
  12.  current=current->next; 
  13.  } 
  14. return false

七、总结及源文件

以上实现了链表的一些常见操作,源文件LinkList.cpp全部代码如下: 

/*
 * 作者: 达闻东
 * 修改日期:2010-04-28 17:10
 * 描述: 实现链表的常见操作
*/

  1. #include<iostream> 
  2. #include<iomanip> 
  3. using namespace std; 
  4.  
  5. /*单链表节点结构*/ 
  6. typedefstruct NodeType 
  7. char elem; 
  8.  NodeType*next; 
  9. }Node; 
  10.  
  11. /*双链表节点结构*/ 
  12. typedefstruct DNodeType 
  13. char elem; 
  14.  DNodeType*next; 
  15.  DNodeType*prev; 
  16. }DNode; 

/*创建链表*/

  1. Node* CreateList(Node*head) 
  2. if(NULL== head)//分配头节点空间 
  3.  head=(Node*)malloc(sizeof(Node)), 
  4.  head->next=NULL; 
  5.  
  6.  Node*current=head ,*temp; 
  7. char ch; 
  8.  
  9. while(1) 
  10.  { 
  11.  cout<<"\n input elem:"
  12.  cin>>ch; 
  13. if('#' == ch)/*#结束输入*/ 
  14. break
  15.  temp=(Node*) malloc (sizeof(Node) ); 
  16.  temp->elem=ch; 
  17.  temp->next=NULL; 
  18.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  19.  current=temp;/*当前节点为链表尾节点*/ 
  20.  
  21.  } 
  22.  
  23. return head; 

/*输出链表*/

  1. void PrintList(Node*head) 
  2.  Node* current=head->next; 
  3.  cout<<"\n List are:"
  4. while(NULL!= current) 
  5.  { 
  6. if(NULL!= current->elem) 
  7.  cout<<setw(5)<<current->elem; 
  8.  current=current->next; 
  9.  } 
  10.  cout<<"\n"

/*插入节点*/

  1. Node*InsertNode(Node*head,char elem) 
  2. if( NULL== head|| NULL== elem) 
  3. return head; 
  4.  
  5.  Node*current=head->next;/*当前节点*/ 
  6.  Node*prev=head;/*前驱节点*/ 
  7.  Node*temp;/*过渡节点*/ 
  8.  
  9. while(current)/*移动至尾节点*/ 
  10.  { 
  11.  prev=current; 
  12.  current=current->next; 
  13.  } 
  14.  
  15.  temp=(Node*) malloc(sizeof(Node) ); 
  16.  temp->elem=elem; 
  17.  temp->next=NULL; 
  18.  prev->next=temp;/*尾节点的后驱指向新节点*/ 
  19.  
  20. return head; 

/*删除节点*/

  1. Node*DeleteNode(Node*head,char elem) 
  2. if(NULL== head|| NULL== elem) 
  3. return head; 
  4. if(NULL== head->next) 
  5. return head; 
  6.  
  7.  Node*prev,*current; 
  8.  prev=head; 
  9.  current=head->next; 
  10.  
  11. while(current) 
  12.  { 
  13. if(current->elem== elem)/*匹配节点元素*/ 
  14.  { 
  15.  prev->next=current->next;/*前驱节点的后驱指向当前节点的下一个节点*/ 
  16.  free(current);/*释放当前节点*/ 
  17. return head; 
  18.  } 
  19.  prev=current; 
  20.  current=current->next;/*移动至下一个节点*/ 
  21.  } 
  22. return head; 

/*单链表逆置*/

  1. Node*ReverseList(Node*head) 
  2. if(NULL== head) 
  3. return head; 
  4. if(NULL== head->next) 
  5. return head; 
  6. if(NULL== head->next->next) 
  7. return head; 
  8.  
  9.  Node*curr=head->next;/*当前节点*/ 
  10.  head->next=NULL; 
  11.  Node*temp; 
  12.  
  13. while(curr) 
  14.  { 
  15.  temp=curr->next;/*暂存下一个节点*/ 
  16. /*把当前节点插入到head节点后*/ 
  17.  curr->next=head->next; 
  18.  head->next=curr; 
  19.  
  20.  curr=temp;/*移动至下一个节点*/ 
  21.  } 
  22. return head; 

/*求中间节点*/

  1. Node* MiddleNode(Node*head) 
  2. if(NULL== head) 
  3. return head; 
  4. if(NULL== head->next) 
  5. return head->next; 
  6.  
  7.  Node*p1,*p2; 
  8.  p1=head; 
  9.  p2=head; 
  10.  
  11. while(p2->next) 
  12.  { 
  13. /*p2节点移动2个节点位置*/ 
  14.  p2=p2->next; 
  15. if(p2->next)/*判断p2后驱节点是否存在,存在则再移动一次*/ 
  16.  p2=p2->next; 
  17. /*p1节点移动1个节点位置*/ 
  18.  p1=p1->next; 
  19.  } 
  20. return p1; 

/*合并有序单链表*/

  1. Node* MergeList(Node* h1,Node* h2) 
  2. if(NULL== h1|| NULL== h2) 
  3. return h1; 
  4. if(NULL== h1->next) 
  5. return h2; 
  6. if(NULL== h2->next) 
  7. return h1; 
  8.  
  9. Node* curr1,*curr2,*prev1,*temp; 
  10.  prev1=h1;/*链表1的前驱节点*/ 
  11.  curr1=h1->next;/*链表1的当前节点*/ 
  12.  curr2=h2->next;/*链表2的当前节点*/ 
  13.  temp=h2; 
  14. while(curr2) 
  15.  { 
  16. while(curr1&& curr1->elem< curr2->elem)
  17. /*链表1指针移动至大或等于链表2当前元素的位置*/ 
  18.  prev1=curr1,curr1=curr1->next; 
  19.  
  20. /*在链表1中插入链表2的当前元素*/ 
  21.  temp=curr2->next;/*暂存链表2的下一个节点*/ 
  22.  prev1->next=curr2; 
  23.  curr2->next=curr1; 
  24.  
  25. /*链表1移动至新节点*/ 
  26.  curr1=curr2; 
  27. /*链表2移动至下一个节点*/ 
  28.  curr2=temp; 
  29.  } 
  30. return h1; 

/*创建双链表*/

  1. DNode* DoubleList(DNode*head) 
  2. if(NULL== head)//分配头节点空间 
  3.  head=(DNode*)malloc(sizeof(DNode)) ,head->prev=NULL , head->next=NULL; 
  4.  
  5.  DNode*current=head ,*temp; 
  6. char ch; 
  7.  
  8. while(1) 
  9.  { 
  10.  cout<<"\n inputelem:"
  11.  cin>>ch; 
  12. if('#' == ch)/*#结束输入*/ 
  13. break
  14.  temp=(DNode*) malloc (sizeof(DNode) ); 
  15.  temp->elem=ch; 
  16.  temp->next=NULL; 
  17.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  18.  temp->prev=current;/*新节点的前驱指向当前节点*/ 
  19.  current=temp;/*当前节点为链表尾节点*/ 
  20.  } 
  21. return head; 

/*输出双链表*/

  1. void PrintDoubleList(DNode*head) 
  2. if(NULL== head) 
  3. return
  4.  
  5.  DNode* p; 
  6.  p=head; 
  7.  cout<<"\n DoubleListare:"
  8. while(p->next) 
  9.  { 
  10.  p=p->next; 
  11. if(p->elem) 
  12.  cout<<setw(5)<<p->elem; 
  13.  
  14.  } 
  15.  
  16.  cout<<"\n DoubleListare:"
  17. while(p->prev) 
  18.  { 
  19. if(p->elem) 
  20.  cout<<setw(5)<<p->elem; 
  21.  p=p->prev; 
  22.  } 

/*创建循环链表*/

  1. Node* CycleList(Node*head) 
  2. if(NULL== head)/*分配头节点空间*/ 
  3.  head=(Node*)malloc(sizeof(Node)),head->next=NULL; 
  4.  
  5.  Node*current=head ,*temp; 
  6. char ch; 
  7.  
  8. while(1) 
  9.  { 
  10.  cout<<"\n inputelem:"
  11.  cin>>ch; 
  12. if('#' == ch)/*#结束输入*/ 
  13. break
  14.  temp=(Node*) malloc (sizeof(Node) ); 
  15.  temp->elem=ch; 
  16.  temp->next=NULL; 
  17.  current->next=temp;/*当前节点的后驱指向新节点*/ 
  18.  current=temp;/*当前节点为链表尾节点*/ 
  19.  
  20.  } 
  21.  current->next=head;/*尾节点指向头节点*/ 
  22. return head; 

/*判断链表是否有环(循环链表)*/

  1. bool IsCycleList(Node*head) 
  2. if(NULL== head) 
  3. return false
  4. if(NULL== head->next) 
  5. return false
  6.  Node*current=head->next; 
  7. while(current) 
  8.  { 
  9. if(head== current->next) 
  10. return true
  11.  current=current->next; 
  12.  } 
  13. return false
  14. int main() 
  15.  Node* head,*p; 
  16.  Node* head2,*head3; 
  17.  DNode* dHead; 
  18. char ch; 
  19.  head= NULL; 
  20.  head2=NULL; 
  21.  head3=NULL; 
  22.  dHead=NULL; 
  23.  
  24. //head=(Node*)malloc ( sizeof( Node) ); 
  25. //head->next= NULL; 
  26.  
  27. //创建单链表 
  28.  head=CreateList(head); 
  29.  PrintList(head); 
  30.  
  31.  head2=CreateList(head2); 
  32.  PrintList(head2); 
  33.  
  34. //插入节点 
  35.   cout<<"\n input elem toinsert:"
  36.  cin>>ch; 
  37.  InsertNode(head,ch); 
  38.  PrintList(head); 
  39.  
  40. //删除节点 
  41.   cout<<"\n input elem todelete:"
  42.  cin>>ch; 
  43.  DeleteNode(head,ch); 
  44.  PrintList(head); 
  45.  
  46. //单链表逆置 
  47.   head=ReverseList(head); 
  48.  cout<<"\n Reversed !"
  49.  PrintList(head); 
  50.  
  51. //求中间节点 
  52.  p=MiddleNode(head); 
  53.  cout<<"\n Middle Nodeis:"
  54.  cout<<p->elem<<endl; 
  55.  
  56. //合并有序单链表 
  57.  MergeList(head,head2); 
  58.  cout<<"\n Merged!"
  59.  PrintList(head); 
  60.  
  61. //创建双链表 
  62.  dHead=DoubleList(dHead); 
  63.  PrintDoubleList(dHead); 
  64.  
  65. /*创建循环链表并判断是否有环*/ 
  66.  head3=CycleList(head3); 
  67.  cout<<IsCycleList(head3); 
  68. return 0; 


 

(达闻东)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201109/15081.html]
本文出处:网络 作者:达闻东
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容