单链表的基本操作实现

本文介绍了一个使用模板机制实现的单链表类,支持int和char类型数据的插入、删除和查找等操作,并通过实例演示了如何利用头插法创建单链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的:通过实际操作单链表,掌握单链表的链式储存结构以及验证单链表及其操作的实现并进一步理解算法与程序的关系。

 

内容:用头插法建立带头结点的单链表并对已创建的单链表实现插入、删除、查找等基本操作。

 

特点:手动输入链表的数据、融入模板机制,可以自由选择输入数据的类型(intchar

 

单链表类的定义

#include<iostream>
#include<iomanip>   //使用了setw()
using namespace std;

template<class T>
struct Node
{
	T data;
	Node<T>*next;
};

template<class T>
class LinkList
{
public:
	LinkList();   /*无参构造函数,建立只有头结点的空链表*/
	LinkList(T a[],int n);  /*建立有n个元素的单链表*/
	~LinkList();
	void Insert(int i,T x);   /*在第i个位置中插入元素值为X的结点*/
	int Length();  /*求单链表的长度*/
	T Get(int i);   /*按位查找,在单链表中查找第i个结点的元素值*/
	int Locate(T x);    /*按值查找*/
	T Delete(int i);   /*删除链表中第i个结点*/
	void PrintList();   /*按序号依次输出各元素*/

private:
	Node<T>*first;  /*单链表的头指针*/
};

成员函数定义

template<class T>
LinkList<T>::LinkList()
{
	first=new Node<T>;
	first->next=NULL;
}

//头插法创建空链表
template<class T>
LinkList<T>::LinkList(T a[],int n)
{
   Node<T>*s;
   first=new Node<T>;
   first->next=NULL;

   for(int i=0;i<n;i++)
   {
     s=new Node<T>;
	 s->data=a[i];
	 s->next=first->next; first->next=s;  
   }
   
}

template<class T>
LinkList<T>::~LinkList()
{
	Node<T>*t;
	while(first!=NULL)
	{
	  t=first;
	  first=first->next;
	  delete t;
	}
}

//单链表插入算法
template<class T>
void LinkList<T>::Insert(int i,T x)
{
    Node<T>*p=first;
	Node<T>*s;
	int count=0;
	while(p!=NULL&&count<i-1)
	{
	  p=p->next;
	  count++;
	}
	if(p==NULL) throw "没有找到结点";
	else
	{
	  s=new Node<T>;
	  s->data=x;   
	  s->next=p->next;  
	  p->next=s;
	}
}

//求线性表的长度
template<class T>
int LinkList<T>::Length()
{
   Node<T>*p=first->next;
   int count=0;
   while(p!=NULL)
   {
      p=p->next;
	  count++;
   }
   return count;
}

//遍历线性表的数据
template<class T>
void LinkList<T>::PrintList()
{
   Node<T>*q=first->next;
   while(q!=NULL)
   {
      cout<<q->data<<endl;
	  q=q->next;   
   }
}

//按位查找数据
template<class T>
T LinkList<T>::Get(int i)
{
    Node<T>*p=first->next;
	int count=0;
	if(p!=NULL)
	{
		while(count<i)
		{
			if(count==i-1)
			{
			  cout<<'\n'<<p->data<<endl;
			}
			p=p->next;
			count++;
		}
	}
	else
	{  
	 return 0;
	}
}

//按值查找数剧
template<class T>
int LinkList<T>::Locate(T x)
{
    Node<T>*p=first->next;
	int count;
	for(count=1;p!=NULL;count++)
	{
	  if(p->data==x)
	  {
	    return count;    
	  }
	  p=p->next;
	}
	return 0;
}

//删除链表中第i个结点
template<class T>
T LinkList<T>::Delete(int i) 
{
    Node<T>*p=first;
	int count=0;
	if(p!=NULL)
	{
		while(count<i)
		{
			if(count==i-1)
			{
			  Node<T>*q=p->next;
			  T x=q->data;   //暂存被删除的结点
			  p->next=q->next;
			  delete q;
			  return x;
			}
			p=p->next;
			count++;
		}
	}
	else
	{  
	 throw "位置";
	 return 0;
	}
}

主函数代码

int main()
{
	   int n;int w; 
	   cout<<'\n'<<"请选择您要输入的数据类型:"<<endl;
	   cout<<"1.int类型"<<'\t'<<"2.char类型"<<'\n'<<endl;
	   cin>>w;
	   switch(w)
	   {
		   
	   case 1:
		   {
		       int a[100];int i;
			   cout<<"请输入数组的大小"<<endl;
			   cin>>n;
			   cout<<"请输入数组元素:"<<endl;   //头插法插入数据
			   for(i=0;i<n;i++)
			   {
				   cin>>a[i];
			   }
			   LinkList<int>one(a,n);    //带参构造函数
			   cout<<'\n'<<"线性表的长"<<one.Length()<<endl; 
			   cout<<'\n'<<"线性表中的内容:"<<endl;    
	           one.PrintList();  //输出线性表的数据

			    //按位查找
			   int s;
			   cout<<'\n'<<"请输入要查找数据的序号:";
			   cin>>s;
			   cout<<'\n'<<"您所查询的数据以及所在的序号为:";
			   cout<<one.Get(s)<<endl;

			   //按值查找
			    int x;
			    cout<<'\n'<<"请输入要查找的数据:";
			    cin>>x;
			    cout<<"你所查找的值所在的位置为:"<<one.Locate(x)<<endl;

				//按序号删除数据
			   int k;
			   cout<<'\n'<<"请输入需要删除的数据序号:";
			   cin>>k;
			   cout<<"删除成功!你所删除的数据为:"<<one.Delete(k)<<endl;
			   cout<<'\n'<<"线性表的内容为:"<<endl;
			   one.PrintList();  //输出线性表的数据
		   }
		   break;
	   case 2:
		   {
			   char a[100];int i;
			   cout<<"请输入数组的大小"<<endl;
			   cin>>n;
			   cout<<"请输入数组元素:"<<endl;   //头插法插入数据
			   for(i=0;i<n;i++)
			   {
				   cin>>a[i];
			   }
			   LinkList<char>one(a,n);    //带参构造函数
			   cout<<'\n'<<"线性表的长"<<one.Length()<<endl; 
			   cout<<'\n'<<"线性表中的内容:"<<endl;    
	           one.PrintList();  //输出线性表的数据

			    //按位查找
			   int s;
			   cout<<'\n'<<"请输入要查找数据的序号:";
			   cin>>s; 
			   cout<<"您所查询的数据为:";
			   cout<<one.Get(s)<<endl;

			    //按值查找
			   char x;
			   cout<<"请输入要查找的数据:";
			   cin>>x;
			   cout<<one.Locate(x)<<endl;

			   //按序号删除数据
			   int k;
			   cout<<'\n'<<"请输入需要删除的数据序号:";
			   cin>>k;
			   cout<<"删除成功!你所删除的数据为:"<<one.Delete(k)<<endl;
			   cout<<'\n'<<"线性表的内容为:"<<endl;
			   one.PrintList();  //输出线性表的数据
		   }
		   break;
	   }
	  
   return 0;
}



输入数据为int类型时的输出结果






输入数据为char类型时的输出结果









心得:

1.单链表中,头指针指向第一个元素所在的结点,具有标识单链表的作用,在使用头插法时不需要移动头结点。

2.在单链表上实现插入和删除操作,无需移动结点,在工作指针指向合适的位置后,仅需修改结点之间的链接关系。

3.值得注意的是数组储存的下标是从0开始,而查询时的序号是从1开始,所以要注意查询的判断条件。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值