本文计划分析的链表题目:
单链表相关
双链表相关
单链表:
链表节点结构
typedef struct Snode { int data; struct Snode* next; } SLinkNode;
单链接的创建,采用后接方式,即后插入节点在后面,先插入节点在前面:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <memory.h> 4 5 typedef struct Snode{ 6 int data; 7 struct Snode* next; 8 }SLinkNode; 9 10 11 int main(int argc, char *argv[]) 12 { 13 int arr[] = {6,9,23,56,88,797,67,34,76,343}; 14 SLinkNode* head = NULL; 15 SLinkNode* pre, *cur; 16 int i= 0,j =0; 17 for( i = 0; i<10 ; ++i ){ 18 printf("%d\t", arr[i]); 19 } 20 puts("\n"); 21 22 23 24 for(i =0 ;i < 10 ; ++i ){ 25 cur = (SLinkNode *) malloc(sizeof (SLinkNode)); 26 cur -> data = arr[i]; 27 cur -> next = NULL; 28 if(head == NULL){ 29 head = pre = cur ; 30 }else{ 31 pre ->next = cur; 32 pre = cur; 33 } 34 } 35 36 cur = head; 37 while(cur != NULL){ 38 printf("%d\t", cur ->data); 39 cur = cur ->next; 40 } 41 42 return 0; 43 }
单链表节点删除,单链表的节点删除方法相对简单
主要遇到的问题有:
单链接节点插入也相对简单,主要遇到问题
单链表的逆转:
1 SLinkNode* reverseLink(SLinkNode* head) 2 { 3 if(head == NULL || head->next == NULL) 4 { 5 return head; /*链表为空或只有一个元素则直接返回*/ 6 } 7 8 SLinkNode *tmp = NULL, 9 *pre = head, 10 *cur = head -> next; 11 while(cur != NULL) 12 { 13 tmp = cur->next; 14 cur->next = pre; 15 if( pre == head ){ 16 pre -> next = NULL; 17 } 18 pre = cur; 19 cur = tmp; 20 } 21 22 head = pre ; 23 return head; 24 }
创建含有环的单链表
SLinkNode* cycleNode ; for(i =0 ; i < 10 ; ++i ) { cur = (SLinkNode *) malloc(sizeof (SLinkNode)); cur -> data = arr[i]; cur -> next = NULL; if(head == NULL) { head = pre = cur ; } else { pre ->next = cur; pre = cur; } if(i ==5 ){ cycleNode = pre; } } cur -> next = cycleNode;
利用两一个指针,一个速度是另外一个的两倍。
即一个指针慢指针:每次移动一个结点;一个快指针,每次移动两结点。
若有环:则两指针会在某一点相遇;若无环:则快指针会先走到链表末尾。
代码如下:
int isCircleLink(SLinkNode* head) { if(head == NULL || head ->next == NULL) { return 0; } SLinkNode *slow = head, *fast = head; while (fast && fast-> next) { slow = slow ->next; fast = fast ->next -> next; if (slow == fast) { return 1; } } return 0; }
求含有环单链表的环汇总第一个节点:
解法一 :
假设快指针和慢指针在蓝色圆圈所表示结点p处相遇,则它们走过的路径长度分别为:
快指针fast = 非环段链表长度L + 环上链表结点个数C + 从p到交点的弧长S
慢指针slow = 非环段链表长度L + 从p到交点的弧长S
又有fast = 2*slow
故 L = C - S
因此:设两个指针,一个从表头开始遍历,一个从p开始遍历,相遇的结点就是环的起点。代码如下:
SLinkNode* beginOfCircle(SLinkNode *head) { if( head == NULL || head -> next == NULL) { return NULL; } SLinkNode *slow = head, *fast = head; while (fast && fast-> next) { slow = slow ->next; fast = fast ->next -> next; if (slow == fast) { break; } } if(fast == NULL || fast->next == NULL) //此时链表无环; { return NULL; } fast = head; while (slow != fast) { slow = slow-> next; fast = fast-> next; } return fast; }
两外一种思路,求两个链表的共同点
SLinkNode* beginOfCircle2(SLinkNode *head) { if( head == NULL || head -> next == NULL) { return NULL; } SLinkNode *slow = head, *fast = head; while (fast && fast-> next) { slow = slow ->next; fast = fast ->next -> next; if (slow == fast) { break; } } if(fast == NULL || fast->next == NULL) //此时链表无环; { return NULL; } fast = slow ->next ; slow -> next = NULL; int len1 = 0; int len2 = 0; slow = head ; while(slow != NULL) { len1++; slow =slow-> next; } slow = fast ; while(slow != NULL) { len2++; slow =slow-> next; } int len = 0 ; if(len1 > len2) { len = len1 -len2 ; slow = head; while(slow !=NULL && len >0) { --len; slow = slow -> next; } while(fast != NULL && slow != NULL && fast != slow ){ fast = fast ->next; slow = slow -> next; } if(fast == slow){ return fast; }else{ return NULL; } }else if(len1 < len2){ len = len2 -len1 ; while(fast != NULL && len >0 ) { -- len; fast = fast -> next; } slow = head; while(fast != NULL && slow != NULL && fast != slow ){ fast = fast ->next; slow = slow -> next; } if(fast == slow){ return fast; }else{ return NULL; } }else{ slow = head; while(fast != NULL && slow != NULL && fast != slow ){ fast = fast ->next; slow = slow -> next; } if(fast == slow){ return fast; }else{ return NULL; } } }
4、判断链表是否相交
a、无环链表情况:
单列一篇。