2019年真题
题目:设线性表L=(a1,a2,a3,......,a(n-2),a(n-1),a(n)),采用带头结点的单链表保存,链表中的结点定义如下。请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到新线性表L'=(a1,a(n),a2,a(n-1),a3,a(n-2),......)。
typedef struct node {
int data;
struct node *next;
} NODE;
思路分析:①先找到链表的中心结点,使用两个指针p,每次p走一步,q走两步,当q到链表尾时,p正好在链表中心结点。②将链表后半段原地逆置。③将单链表前后两段中依次各取一个结点,进行重排。
NODE *reverseList(NODE *head) {
//将指针全部反转
NODE* pre = NULL;
NODE* cur = head;
NODE* tmp = NULL;//记录cur的下一个结点
while(cur != NULL) {
//记录当前节点的下一个节点
tmp = cur->next;
//然后将当前节点指向pre
cur->next = pre;
//pre和cur节点都前进一位
pre = cur;
cur = tmp;
}
return pre;
}
void changeList(NODE *head) {
NODE *p, *q, *temp;
p = q = head;
//1、找到中间结点
while(q->next != NULL) {
p = p->next;
q = q->next;
if(q->next != NULL) {//q走两步。用if再判断一次是为了防止走一步后就已到队尾,出现NULL->next异常
q = q->next;
}
}
//此时p指向链表L的中心结点 n/2,向下取整。
//2、后半段链表反转。
NODE *back = reverseList(p-next);//将后半段链表逆置,back指向后半段链表的第一个节点。
NODE *pre = head->next;