void change_list(NODE *h) { NODE *p,*q,*r,*s; p=q=h; while(q->next!=NULL)//寻找中间结点 { p=p->next;//p走一步 q=q->next; if(q->next!=NULL) q=q->next; //q走两步 } q=p->next;//p所指结点为中间结点,q为后半段链表的首结点 p->next=NULL; while (q!=NULL)//将链表后半段逆置 { r=q->next; q->next=p->next; p->next=q; q=r; } s=h->next;//s指向前半段的第一个数据结点,即插入点 q=p->next;//q指向后半段的第一个数据结点 p->next=NULL; while(q!=NULL)//将链表后半段的结点插入到指定位置 { r=q->next;//r指向后半段的下一个结点 q->next=s->next; //将q所指结点插入到s所指结点之后 S->next=q; S=q->next;//s指向前半段的下一个插入点 q=r; } }
#include<stdio.h> #include<malloc.h> typedef struct node { struct node* next; int data; }node; node* initlinklist(int a[], int size) { node* p = (node*)malloc(sizeof(node)); p->data = a[0]; p->next = NULL; node* temp = p; for (int i = 1; i < size; i++) { node* b = (node*)malloc(sizeof(node)); b->data = a[i]; b->next = NULL; temp->next = b; temp = temp->next; } return p; } void printlist(node* p) { node* temp = p; while (temp != NULL) { printf("%d", temp->data); if (temp->next != NULL) printf("->"); temp = temp->next; } putchar(10); } //找到中间节点 node* findmiddle(node* head) { node* slow = head, * fast = head; while (fast&&fast->next) { slow = slow->next; fast = fast->next->next; } return slow; } //反转链表 node* reversive(node* head) { node* newhead = NULL,*temp=NULL; if (head==NULL||head->next==NULL) return head; while(head!=NULL){ temp = head; head = head->next; temp->next = newhead; newhead = temp; } return newhead; } //重新链接链表 void recover(node* head) { if (!head || !head->next) return; node* middle = findmiddle(head); node* secondhalf = middle->next; middle->next = NULL;//切断 secondhalf = reversive(secondhalf);//翻转后半段 node* firsthalf = head; while (secondhalf) { node* temp1 = firsthalf->next; node* temp2 = secondhalf->next; firsthalf->next = secondhalf; secondhalf->next = temp1; firsthalf = temp1; secondhalf = temp2; } } int main() { int a[] = { 1,2,3,4,5,6,7,8,9 }; int size = sizeof(a) / sizeof(a[0]); node* head = initlinklist(a, size); printlist(head); recover(head); printlist(head); return 0; }
findmiddleO(n)
reversiveO(n)
recoverO(n)
总复杂度O(n)
1
https://rainbow452.notion.site/P1496-85038b5808d2403cbd356ba83562c185?pvs=4
Austin00 回复 Austin00: typedef struct node { int data; // 节点数据 struct node *next; // 指向下一个节点的指针 } NODE; void f(NODE *l, int len) { int t = len / 2; // 计算链表中间的位置 NODE *x = l->next, *y = l; // x 初始化为第二个节点,y 初始化为头节点 // 将 y 移动到链表的中间位置 while (t--) { y = y->next; // 移动 y 到链表的中间节点 } // 在中间位置断开链表,并将 y 移动到后半部分的第一个节点 NODE *o = y; // o 保存中间节点的位置 y = y->next; // y 移动到链表的后半部分的第一个节点 o->next = NULL; // 断开前半部分与后半部分的连接 // 创建一个新的空链表 z,用于存储逆序后的节点 NODE *z = (NODE *)malloc(sizeof(NODE)); z->next = NULL; // 逆序链表的后半部分(从 y 开始) while (y != NULL) { NODE *p = y->next; // 保存 y 的下一个节点 y->next = z->next; // 将 y 插入到 z 链表的开头 z->next = y; // 更新 z->next 为 y y = p; // 移动 y 到下一个节点 } // 合并链表前半部分(x)和逆序后的后半部分(z->next) while (z->next != NULL) { NODE *p = z->next->next; // 保存 z->next 的下一个节点 z->next->next = x->next; // 将 z->next 插入到 x 的后面 x->next = z->next; // 更新 x->next 为 z->next z->next = p; // 更新 z->next 为 p x = x->next->next; // x 向前移动两个节点 } }
逆置后半段链表,两个指针就能实现
参考答案:
(1)算法的基本...
用户登录可进行刷题及查看答案
(1)算法的基本设计思想:
算法分3步完成。第1步,采用两个指针交替前行,找到单链表的中间结点;第2步,将单链表的后半段结点原地逆置;第3步,从单链表前后两段中依次各取一个结点,按要求重排。
(2)算法实现:
(3)算法的时间复杂度:
参考答案的时间复杂度为O(n)。
登录后提交答案