线性表算法设计题1

1.设线性表L=(a1,a2,a3,…,a[n-2],a[n-1],an)采用带头结点的单链表保存,链表中结点定义如下:
typedef struct node{
int data;
struct node* next;
}NODE;
请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的个结点得到线性表L’=(a1,an,a2,a[n-1],a3,a[n-2],…)。
要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用c或c++语言描述算法,关键之处给出注释。
(3)说明你所设计的算法的时间复杂度。【2019年全国试题41(13)分】

答:(1)将原有链表从中间分为两部分,分别是(a1,a2,a3,…a[n/2])和(a[n/2+1],a[n/2+2],…,a[n])。将后一部分链表逆置,再将两个链表合并。
(2)核心语句

int i=1;
p=head->next;	//设head是指向带头结点的单链表的指针
while(i<n/2){	//n为元素个数(题目有提示)
	p=p->next;//找到两个链表的分界点,即中间结点
	i++;
}
r=p->next;     //r即为第二个链表的头结点
p->next=null;//p结点是前一半的尾结点
q=null;	     //为逆置做准备,q指向逆置表的首元结点
while(r){//链表逆置
	p=r->next;//暂存后继
	r->next=q;//就地逆置
	q=r;		//r(或q)指向链表新首元
	r=p;		//指向待逆置结点
}
p=head->next;//head是指向带头结点的单链表的指针,p指向链表的第一个元素
while(p->next&&q->next){	
	p->next=r;	//暂存两链表后继
	q->next=s;	
	p->next=q->next;	//合并链表,将q结点插入到对应p结点的后面
	p=r;				//恢复指向待合并结点
	q=s;			
}
if(p->next==null)	//*避免n为奇数,这步有些小问题,稍后修改*
	p->next=q;
else
	q->next=p;

(3)算法的时间复杂度为O(n)。

总结
1.算法涉及
(1)拆分链表
(2)逆置链表
(3)合并链表

逆置链表的几种拓展:
1.无头结点的单链表的逆置
2.带附加头结点的单链表的逆置

eg1:有一个无头结点的单链表,结点有数据域data、指针域next,表头指针为h,通过遍历链表,将链表中所有的链接方向逆转。要求逆转后的链表的表头指针h指向原链表的最后一个结点。算法如下所示。【南京理工大学2005二、1(3分)】

void Inverse(&h){
	if(h==null)
	return ;
	p=h->next;
	pr=null;
	while(p){
	h->next=pr;
	pr=h;
	h=p;
	p=p->next;
	}
	head->next=pr;
}

eg2:以下程序的功能就是实现带附加头结点的单链表数据结构逆序链接【西南交通大学2000一、9】

void reverse(pointer h){
/*h为附加头结点*/
	pointer p,q;
	p=h->next;
	h->next=null;
	while(p!=null){
	q=p;
	p=p->next;
	q->next=h->next;
	h->next=q;
	}
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值