双向链表的创建和相关操作

    双向链表其实是单链表的改进。 当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。

   在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。

   在c语言中双向链表结点类型可以定义为:

typedef struct Node
{
	int item;
	struct Node *pre;
	struct Node *next;
}DListNode,*DList;

下面的代码就是对双向链表的创建和相关操作:

/***************************************************************************
 *name:jae chia                                                            *
 *date:2014.8.29                                                           *
 *version: 1.0                                                             *
 **************************************************************************/
#include<iostream>
#include<cassert>
using namespace std;

//双向链表的建立与操作
typedef struct Node
{
	int item;
	struct Node *pre;
	struct Node *next;
}DListNode,*DList;
DList InsertNodeToTail(DList head,int data)//将节点插入到双向链表的尾部
{
	if(head==NULL)
	{
		head=(DList)malloc(sizeof(DListNode));
		assert(head!=NULL);
		head->item=data;
		head->next=NULL;
		head->pre=NULL;
	}
	else
	{
		DListNode *newnode=(DList)malloc(sizeof(DListNode));//创建新的链表节点
		assert(newnode!=NULL);
		newnode->item=data;
		newnode->next=NULL;
		newnode->pre=NULL;

		DListNode *p=head;
		while(p->next!=NULL)
		{
			p=p->next;
		}
		p->next=newnode;
		newnode->pre=p;
	}
	return head;
}

DList InsertDListByOrder(DList head,int data)//这里的插入操作是按序插入(保证双向链表中的节点以递增有序)
{
	DListNode *newnode=(DList)malloc(sizeof(DListNode));
	assert(newnode);
	newnode->item=data;
	//newnode->next=NULL;
	//newnode->pre=NULL;

	DListNode *p=head;
	DListNode *prenode;
	for(;p!=NULL;p=p->next)
	{   
		prenode=p;
		if(newnode->item <=p->item)
			break;     
	}
	if(p==NULL)//如果遍历整个链表,结点的值都比要插入的小,那么只能在尾端插入
	{
		prenode->next=newnode;
		newnode->pre=prenode;
		newnode->next=NULL;
	}
	else if(p==head)//如果链表中的数都比要插入的数大则在头部插入;
	{
		newnode->pre=NULL;
		newnode->next=head;
		head=newnode;
	}
	else   //在中间插入
	{
		p->pre->next=newnode;
		newnode->pre=p->pre;

		newnode->next=p;
		p->pre=newnode;
	}
	return head;
}

bool FindNode(DList head,int data)//查找链表中含有某元素的节点是否存在
{
	if(head==NULL)
	{
		cout<<"the Dlist is NULL"<<endl;
		return false;
	}
	DListNode *p=head;
	while(p!=NULL)
	{
		if(p->item==data)
			return true;
		p=p->next;
	}
	return false;
}

DList DeleteNode(DList head,int data)//删除节点
{
	DListNode *p=head;
	while(p!=NULL)
	{
		if(p->item==data)
			break;
		p=p->next;
		
	}
	if(p==NULL)
	{
		cout<<"the node with data is not existed in the List"<<endl;
		exit(0);
	}
	if(p==head)//要删除的结点恰好是双向链表的头结点
	{
		DListNode *tmp=head;
		head=head->next;
		head->pre=NULL;//---------------------------------------------------
		free(tmp);
	}
	else if(p->next==NULL)//如果要删除的节点是链表的最后一个节点
	{
		p->pre->next=NULL;
		free(p);
	}
	else //删除中间节点
	{
		p->pre->next=p->next;
		p->next->pre=p->pre;
	}
	return head;  
}
void PrintDList(DList head)//打印
{
	cout<<"现在,链表如下:"<<endl;
	if(head==NULL)
	{
		cout<<"the Dlist is NULL"<<endl;
		return ;
	}
	DListNode *p=head;
	while(p!=NULL)
	{
		cout<<p->item<<" ";
		p=p->next;
	}
	cout<<endl<<endl;
}
void DestroyDList(DList head)//销毁双向链表
{
	DListNode *p=head;
	while(p!=NULL)
	{
		DListNode *tmp=p;
		p=p->next;
		free(tmp);
	}
}

void Test()
{
	DListNode *head=NULL;

	for(int i=0;i<10;i++)   /*利用尾部插入来构造双向链表*/
		head=InsertNodeToTail(head,i);
	PrintDList(head);
    
	int a;
	cout<<"输入要查找的结点的值"<<endl;
	cin>>a;
	if(FindNode(head,a))
		cout<<"结点存在!"<<endl<<endl;
	else
		cout<<"结点不存在!"<<endl<<endl;

	cout<<"删除结点4..."<<endl;    /*删除指定节点*/
	head=DeleteNode(head,4);
	PrintDList(head);

	cout<<"插入结点4..."<<endl;     /*按序插入*/
	head=InsertDListByOrder(head,4);
    PrintDList(head);
    
	cout<<"删除头结点..."<<endl;    /*删除指定节点*/
	head=DeleteNode(head,0);
	PrintDList(head);
    
	cout<<"删除尾结点..."<<endl;
	head=DeleteNode(head,9);
	PrintDList(head);
    
	cout<<"插入头结点..."<<endl;     /*按序插入*/
	head=InsertDListByOrder(head,0);
    PrintDList(head);
	
	cout<<"插入尾结点..."<<endl;     /*按序插入*/
	head=InsertDListByOrder(head,10);
    PrintDList(head);

    DestroyDList(head);
}
int main(void)
{
	Test();
}

运行:






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值