单链表相关问题
先定义一个单链表结构体:
typedef int DataType; typedef struct _list { DataType data; struct _list *next; }List,*PList;
相关操作:
1,几个基本操作
PList InsHead(PList *head,DataType x) //在头部插人 { PList newNode = (List *)malloc(sizeof(List)); //直接插入 newNode->data = x; newNode->next = *head; *head = newNode; return *head; } PList InsEnd(PList *head,DataType x) //在尾部插入 { PList newNode= (List *)malloc(sizeof(List)); if (*head == NULL) { newNode->data = x; newNode->next = NULL; *head = newNode; } else { PList workNode = *head; while(workNode->next != NULL) //先找到尾部 { workNode = workNode->next; } workNode->next = newNode; newNode->data = x; newNode->next = NULL; } return *head; }
void PrintList(PList *head) //输出链表元素 { PList workNode = *head; while (workNode != NULL) { printf("%d—>",workNode->data); workNode = workNode->next; } printf("NULL"); printf("\n"); } PList EndOfList(PList *head) //找到链表的尾节点 { PList workNode = *head; while (workNode->next != NULL) { workNode = workNode->next; } return workNode; } int LenOfList(PList *head) //返回链表的长度 { int len = 0; PList workNode = *head; while (workNode != NULL) { len++; workNode = workNode->next; } return len; }
2,链表相交
如果两个链表相交,则它们的尾节点一定是指向同一地址。
int IsInsect(PList *List1,PList *List2) //判断两个链表是否相交 { PList workNode1 = EndOfList(List1); PList workNode2 = EndOfList(List2); if (workNode1 == workNode2) { return 1; } else { return 0; } } PList InsectNode(PList *List1,PList *List2) //返回链表的交点 { PList RetNode = NULL; if (IsInsect(List1,List2)) { PList workNode1 = *List1; PList workNode2 = *List2; int len1 = LenOfList(&workNode1); int len2 = LenOfList(&workNode2); int len = len1 - len2; if (len > 0) //让两链表在同一起跑线,然后再往后找 { for (int j = 0; j < len; j++) { workNode1 = workNode1->next; } } else { len = abs(len); for (int j = 0; j < len; j++) { workNode2 = workNode2->next; } } while(workNode1 != workNode2) { workNode1 = workNode1->next; workNode2 = workNode2->next; } RetNode = workNode1; } return RetNode; } int LenOfInsect(PList *List1,PList *List2) //链表相交部分的长度 { if (IsInsect(List1,List2)) { int i = 0; PList workNode1 = *List1; PList workNode2 = *List2; int len1 = LenOfList(&workNode1); int len2 = LenOfList(&workNode2); int len = len1 - len2; if (len > 0) { for (int j = 0; j < len; j++) { workNode1 = workNode1->next; } } else { len = abs(len); for (int j = 0; j < len; j++) { workNode2 = workNode2->next; } } while(workNode1 != workNode2) { workNode1 = workNode1->next; workNode2 = workNode2->next; } while(workNode1 != NULL) { i++; workNode1 = workNode1->next; } return i; } else { return 0; } }
3,链表是否成环
先定义一个结构体,用来记录链表是否有环,及环中的某个节点。
typedef struct _Ret { PList Node; int ret; }Ret,*PRet;
PRet IsCycleList(PList *head) //链表是否成环 { PRet RetSruct = (PRet)malloc(sizeof(Ret)); PList workNode1 = *head; PList workNode2 = workNode1; while (workNode1->next&&workNode2->next->next) { workNode1 = workNode1->next; workNode2 = workNode2->next->next; if (workNode1 == workNode2) //如果成环,一个走1步,一个走2步,它们必定能碰到一起 { RetSruct->Node = workNode1; RetSruct->ret = 1; return RetSruct; } } return NULL; } int LenOfCycle(PList *head) { if ((IsCycleList(head))->ret) { int i = 0; PList Node = (IsCycleList(head))->Node; PList workNode = Node; while (workNode->next != Node) { i++; workNode = workNode->next; } i++; //从这个节点起再次访问到这个节点,即为环的长度 return i; } return 0; } PList NodeOfCycle(PList *head) { if ((IsCycleList(head))->ret) { PList Node = (IsCycleList(head))->Node; //先找到环内一个节点 PList ReNode = Node->next; //下一个节点 PList RetNode = NULL; Node->next = NULL; //从环的某个节点处断开,转换成2个相交链表 RetNode = InsectNode(head,&ReNode); Node->next = ReNode; //还原链表 return RetNode; } return NULL; }

浙公网安备 33010602011771号