数据结构习题——将链表L(a1,a2,a3,...,an-2,an-1,an)改造成(a1,an,a2,an-1,a3,an-2,...)

前言

王道2019统考真题

正文

题目

设链表L(a1,a2,a3,…,an-2,an-1,an)采用头结点的单链表保存
请设计一个空间复杂度为O(1)时间上尽可能高效的算法,重新排列L,得到线性表变成(a1,an,a2,an-1,a3,an-2,…)

关键

  1. 先找出链表L的中间点,为此设置了两个指针p和q,指针p每次走一步,q每次走两步,当指针q达到链尾时,指针p正好在链表的中间点
  2. 然后将L的后半部分原地逆置
  3. 从单链表前后两段中以此各取一个结点,按要求重排

这道题涉及了链表的双指针法,链表的逆置,链表的基本操作(头插等),值得自己慢慢消化

代码

void Change_list(Linklist h){
	LNode *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所指结点为中点 
	p->next=NULL;		//q为后半链表的首结点 
	while(q!=NULL){
		r=q->next;
		q->next=p->next;
		p->next=q;
		q=r;
	}
	/*后半部分的链表头插进入前半部分*/
	s=h->next;
	q=p->next;
	p->next=NULL;
	while(q!=NULL){
		r=q->next
		q->next=s->next;//将q所指结点插入到s所指结点之后 
		s->next=q;
		s=q->next;		//将s指向前半段的下一个插入点 
		q=r;
	}
}
  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是C语言实现的算法,将两个循环链表合并为一个循环链表: ```c #include <stdio.h> #include <stdlib.h> typedef struct node{ int data; struct node *next; }Node, *LinkList; void CreateList(LinkList *L, int n)//创建循环链表 { int i; Node *p, *tail; *L = (LinkList)malloc(sizeof(Node)); (*L)->next = NULL; tail = *L; for (i = 0; i < n; i++) { p = (Node*)malloc(sizeof(Node)); scanf("%d", &p->data); tail->next = p; tail = p; } tail->next = *L;//将链表尾结点指向头结点,形循环链表 } void MergeList(LinkList *La, LinkList *Lb, LinkList *Lc)//合并两个循环链表 { Node *pa, *pb, *pc, *tail; pa = (*La)->next; pb = (*Lb)->next; *Lc = pc = *La;//将Lc指向La的头结点,用于存储合并后的循环链表 tail = (*Lc)->next;//tail指向Lc的头结点的下一个结点 while (pa != *La && pb != *Lb) { if (pa->data <= pb->data) { tail->next = pa; tail = pa; pa = pa->next; } else { tail->next = pb; tail = pb; pb = pb->next; } } tail->next = pa == *La ? pb : pa; free(*Lb);//释放Lb的头结点 } void PrintList(LinkList L)//输出循环链表 { Node *p = L->next; while (p != L) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { int n, m; LinkList La, Lb, Lc; printf("请输入La的元素个数:"); scanf("%d", &n); CreateList(&La, n); printf("请输入Lb的元素个数:"); scanf("%d", &m); CreateList(&Lb, m); MergeList(&La, &Lb, &Lc); printf("合并后的循环链表Lc为:"); PrintList(Lc); return 0; } ``` 该算法首先遍历两个循环链表,将它们按照递增的顺序合并到一个新的循环链表Lc中。在遍历过程中,使用tail指针指向Lc的头结点的下一个结点,用于记录Lc的最后一个结点,方便后面插入新的结点。最后释放Lb的头结点,输出合并后的循环链表Lc。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值