Day50:链表排列

122 阅读2分钟

[2019统考真题]

设线性表L=(a1, a2, a3, an-2, an-1, an)采用带头结点的单链表保存,

链表中的结点定义如下:

typedef struct node {
	int data;
	struct node* next;
}NODE;

请设计一个空间复杂度为0(1)且时间上 尽可能高效的算法,重新排列乙中的各结点,得到线性表L=(a1, an, a2, an-1, a3, an-1..)

要求:

1)给出算法的基本设计思想。

1.先找到链表的中间节点;
    分别设立一个快指针和一个慢指针,当快指针到链表末尾时候,慢指针刚好到链表中间节点的位置
2.对链表的后半部夫进行逆置
    利用头插法对链表后半部分进行逆置
3.将逆置完的链表再分别插入前半个链表
      根据题目要求在把逆置好的链表分别插入前面的链表当中

2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。

void changelist(NODE* h) {
	NODE* p , * q , * r , * s;
	p = q = h;
	//寻找中间节点
	while( q->next != NULL ) {
		//p走一步,q走两步
		p = p->next;
		q = q->next;
		if(  q->next != NULL ) {
			q = q->next;
		}
	}
	q = p->next;//p所指节点为中间节点
	p->next = NULL;//q为后半段链表的首届点
	while( q != NULL ) {//将链表后半段逆置
		r = q->next;
		q->next = p->next;
		p->next = q;
		q = r;
	}
	s = h->next;//s指向前半段的第一个数据节点,即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;
		q = r;
	}
}

3)给出你代码的时间复杂度

时间复杂度:O(n)
第一个循环O(n),第二个循环O(n),第三个循环O(n);
总体来看,时间复杂度为O(n);