循环双链表的基本操作实现

目的:巩固线性表的数据结构的储存方法和相关操作,理解循环双链表的特点以及算法的基本思想。


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


特点:不使用模板机制,确定数据类型为int


双链表类的定义

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

struct Node
{
	int data;
	Node *prior;
	Node *next;   //前驱指针、和后继指针
};


class LinkList
{
public:
	LinkList()   /*无参构造函数,建立只有头结点的空链表*/
	{
	Node *first;
	first->next=first;
	first->prior=first;
     }

	LinkList(int a[],int n);  /*建立有n个元素的链表*/
	~LinkList();
	void Insert(int i,int x);   /*在第i个位置中插入元素值为X的结点*/
	int Length();  /*求双链表的长度*/
	int Get(int i);   /*按位查找,在链表中查找第i个结点的元素值*/
	int Locate(int x);    /*按值查找*/
	int Delete(int i);   /*删除链表中第i个结点*/
	void PrintList();   /*按序号依次输出各元素*/

private:
	Node *first;  /*双链表的头指针*/
};


成员函数的定义

//头插法创建链表
LinkList::LinkList(int a[],int n)
{
   Node *s,*f;
   first=new Node;
   f=first;

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

LinkList::~LinkList()
{
	Node *p=first->next;
	Node *t;
    t=first;
	while(p!=first)
	{
	  delete t;
	  t=p;
	  p=p->next;
	}
}

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

//求双链表的长度
int LinkList::Length()
{
   Node *p=first->next;
   
   int count=0;
   while(p!=first)
   {
      p=p->next;
	  count++;
   }
   return count;
}

//遍历双链表的数据
void LinkList::PrintList()
{
   Node *q=first->next;
   while(q!=first)
   {
      cout<<q->data<<endl;
	  q=q->next;   
   }
}

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

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

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

主函数代码

int main()
{
	   int n,i;
	   int a[100];
	   cout<<"******************"<<endl;
	   cout<<"*请输入数组的大小"<<endl;
	    cout<<"******************"<<endl;
	   cin>>n;
	   cout<<'\n'<<endl;
	   cout<<"******************"<<endl;
	   cout<<"*请输入数组元素*"<<endl;
	   cout<<"******************"<<endl;
	   for(i=0;i<n;i++)
		 {
		   cin>>a[i];
		 }
	   LinkList one(a,n);
	   cout<<'\n'<<endl;
	   cout<<"~~~~~~~~~~~~~~~~~~"<<endl;
	   cout<<"线性表的长"<<one.Length()<<endl; 
	   cout<<'\n'<<"线性表中的内容:"<<endl;    
	   one.PrintList();  //输出线性表的数据

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

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

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


发现以及解决的问题:

1.不懂得如何将双链表连接为循环链表,在查阅书籍后才知道,应该把头结点的prior指向first,同时next也指向first,也就是将终端结点的指针域由空指针,改为指向头结点。

2.一开始定义遍历函数的时候没有意识到这是一个循环列表,判断条件设置为工作节点的next是否为空,而出现死循环。后来才意识到判断条件应该是工作节点的next是否为first。


输入、查询功能的执行结果

     


删除操作的执行结果



心得:

1.在循环双链表中秋表长、按位查找、按值查找、遍历等操作的实现与单链表基本相同,不同的是插入和删除操作,使用了前驱结点,使得对数据的插入和删除更加方便。

2.在构造函数定义的时候,注意将结点的地址放到其前驱结点的后继指针域中,也要存放在它的后继结点的前驱指针域中。

3.在双链表中要注意循环条件的设置。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值