C++基本操作:模版类链表

第二次数据结构上机,卡在了模版类的定义…
指针操作比较复杂,调试了很久?

  • 熟悉模版类函数的定义方式
  • 熟悉链表操作
邻居互换

有一个无头结点的单链表,将相邻两个节点互换位置,返回修改后的链表。

例如

输入1->2->3->4,互换后返回2->1->4->3

不可以通过修改链表节点内的值来实现。

#include<iostream>
using namespace std;

template<class Type>
class List;
template<class Type>
class Linknode{
	friend class List<Type>;
	public:
		Linknode(){next=NULL;}
		Linknode(const Type &value){
			data=value;
			next=NULL;
		};
	private:
		Type data;
		Linknode<Type> *next;
}; 
template<class Type>
class List{
	private:
		Linknode<Type> *head;
	public:
		List();//构造函数 
		~List(){};//析构函数 
		bool insert(Type element); //尾插入
		void show(); 
		void showafter();
		bool neighbourexchange();//交换相邻节点 
};

//构造函数
template<class Type>
List<Type>::List()
{
    head=NULL;
 } 

template<class Type>
bool List<Type>::insert(Type element){
	Linknode<Type>*newnode=new Linknode<Type>(element);
	if(newnode==NULL){cerr<<"内存分配错误"<<endl;return false;}
	Linknode<Type> *p=head;
	if(!p) {head=newnode;return true;}
	while(p->next!=NULL)
	p=p->next;
	p->next=newnode;
	return true;
}

template<class Type>
void List<Type>::show(){
	Linknode<Type> *p=head;
	if(head==NULL) cout<<"此为空链表"<<endl;
	else {cout<<"输出链表:"<<endl;
		for(;p;p=p->next)
		cout<<p->data<<"  ";}
	cout<<endl;
}

template<class Type>
void List<Type>::showafter(){
	Linknode<Type> *p=head;
	if(head==NULL) cout<<"此为空链表"<<endl;
	else {cout<<"输出邻居互换后链表:"<<endl;
		for(;p;p=p->next)
		cout<<p->data<<"  ";}
	cout<<endl;
}

template<class Type>
bool List<Type>::neighbourexchange(){
	Linknode<Type> *q=head->next,*p,*r;
	if(!q)  return false;
	head->next=q->next;
	q->next=head;
	head=q;
	if(!head->next->next) return false;
	p=q->next;
	q=p->next;
	while(q->next)
	{	r=q->next;
	    if(r->next==NULL) {
	    	r->next=q;
	    	p->next=r;
	    	q->next=NULL;
	    	return true;
		}
		q->next=r->next;
		r->next=q;
		p->next=r;
		p=q;
		q=p->next;
	}
	return true;
}
int main()
{   int n,i=0,x;
	cout<<"输入链表节点个数:"<<endl;
	cin>>n;
	cout<<"请输入"<<n<<"个整数"<<endl;
	List<int> num;
	for(;i<n;i++)
	{
	cin>>x;
	num.insert(x);
	}
	num.show();
	num.neighbourexchange();
	num.showafter();
	return 0;
}

这题还是比较好写的,写清辅助指针的连接方式和奇数结束情况即可

 

反转前k个节点

有一个无头结点的单链表,将每k个节点反转顺序,返回修改后的链表。
k是不大于链表长度的正整数,如果链表长度不是k的整数倍,则余下的节点保持顺序不变。

例如

链表1->2->3->4->5
当k=2时,输出2->1->4->3->5
当k=3时,输出3->2->1->4->5

不可以通过修改链表节点内的值来实现。试着使程序仅使用常数级的空间复杂度

#include<iostream>
using namespace std;

template<class Type>
class List;
template<class Type>
class Linknode{
	friend class List<Type>;
	public:
		Linknode(){next=NULL;}
		Linknode(const Type &value){
			data=value;
			next=NULL;
		};
	private:
		Type data;
		Linknode<Type> *next;
}; 
template<class Type>
class List{
	private:
		Linknode<Type> *head;
	public:
		List();//构造函数 
		~List(){};//析构函数 
		bool insert(Type element); //尾插入
		void show(); 
		void showafter(int k);
		int listlength();//链表长度 
		bool kreverse(int k,int length);//反转每k个结点 
};

//构造函数
template<class Type>
List<Type>::List()
{
    head=NULL;
 } 

template<class Type>
bool List<Type>::insert(Type element){
	Linknode<Type>*newnode=new Linknode<Type>(element);
	if(newnode==NULL){cerr<<"内存分配错误"<<endl;return false;}
	Linknode<Type> *p=head;
	if(!p) {head=newnode;return true;}
	while(p->next!=NULL)
	p=p->next;
	p->next=newnode;
	return true;
}

template<class Type>
void List<Type>::show(){
	Linknode<Type> *p=head;
	if(head==NULL) cout<<"此为空链表"<<endl;
	else {cout<<"输出链表:"<<endl;
		for(;p;p=p->next)
		cout<<p->data<<" ";}
	cout<<endl;
}

template<class Type>
void List<Type>::showafter(int k){
	Linknode<Type> *p=head;
	if(head==NULL) cout<<"此为空链表"<<endl;
	else {cout<<"每"<<k<<"个节点反转后链表:"<<endl;
		for(;p;p=p->next)
		cout<<p->data<<" ";}
	cout<<endl;
}

template<class Type>
int List<Type>::listlength(){
	int len=0;
	Linknode<Type> *p=head;
	for(;p;p=p->next) 
	len++;
	return len;
}

template<class Type>
bool List<Type>::kreverse(int m,int length){
	if(m>length) {cout<<"反转节点数超过表长"<<endl<<endl;return true;}
	if(m==1) return true;
	Linknode<Type> *p=head,*q=p->next,*t=head,*h=head,*pp=head;
	if(m==2&&length==2) {head=q;q->next=p;p->next=NULL;return true;}
	int i=0,flag=1,headflag=1;
	for(i=1;i<m&&h;i++)
		h=h->next;//h指向下一组k个节点的起始位置 
	while(h){
		flag=1;
		t=h->next;//t储存一组k节点的后继节点 
		if(headflag==1) {head=h;headflag=0;}
		for(i=0;i<m&&h;i++)
		h=h->next;
		while(q!=t&&q)
		{   pp=q->next;
			q->next=p;
			if(flag==1)
			{p->next=h?h:t;flag=0;}
			if(p->next==t&&!h) 
			{  p=q;q=pp;pp=q?q->next:NULL;
				while(q!=t)
				{q->next=p;p=q;q=pp;pp=q?q->next:NULL;}
			    return true;}
			p=q;q=pp;
		}
		if(!h)return true;
		else {p=t;q=p->next;}
	} 
}
int main()
{   int n,i=0,x=0,k=0;
	cout<<"输入链表节点个数:"<<endl;
	cin>>n;
	cout<<"请输入"<<n<<"个整数:"<<endl;
	List<int> num;
	for(;i<n;i++)
	{
	cin>>x;
	num.insert(x);
	}
	num.show();
	cout<<"请输入反转结点数:"<<endl;
    cin>>k;
    cin.sync();
	num.kreverse(k,num.listlength());
	num.showafter(k);
	return 0;
}

130行代码它来了
模版类链表定义照抄前一题,主要复杂在反转节点函数的写法

思路
简单情况单独考虑(k=1/只有两个节点)
h记录下一组k个节点的起始位置(h为NULL则是最后一组反转,便于连接下一组k个节点的头指针)
t保留一组k个节点的后继节点(便于处理之后链表长度不够需要返回的情况)
工作指针p,q,pp依次向后轮转反向连接
注意要先判断head的指向(可以直接判别)
最重要的是处理防止访问空指针的问题:时刻注意判断NULL
还有最后一步操作的分类讨论,调试了好久…
写链表还是把思路理清楚,考虑到所有情况再写

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值