关于双向链表的操作详解

一、概述

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。它其实就是单链表的基础上加入了前驱指针,能够很方便的访问它的前一个数据节点。



从图中可以看出我们的struct需要3个成员:data、prio  、next;
我们再加入一些链表的基本操作可得:
#pragma once
//预防头文件被重复使用

typedef struct DNode
{
	int data;
	struct DNode *next;//后继指针
	struct DNode *prio;//前驱指针
}DNode,*DList;

void InitList(DList plist);
//头插
bool Insert_head(DList plist,int val);
//尾插
bool Insert_tail(DList plist,int val);

DNode *Search(DList plist,int key);

bool Delete(DList plist,int key);

bool IsEmpty(DList plist);

int GetLength(DList plist);

void Show(DList plist);
接下来是各个部分功能的实现:
void InitList(DList plist)//初始化
{
	assert(plist != NULL);判断链表是否成功生成
	if(plist == NULL)
	{
		return ;
	}

	plist->prio = NULL;制成空指针
	plist->next = NULL;
}
头插法:
bool Insert_head(DList plist,int val)
{
	DNode *p = (DNode *)malloc(sizeof(DNode));//在堆上开辟新的节点
	p->data = val;//把数据赋给data

	p->next = plist->next;//先将数据连起来,防止数据丢失
	plist->next = p;连接后继
	p->prio = plist;//连接前驱
	if(p->next != NULL)//判断该节点的下个节点是否有节点,有就要连接下个节
                           // 点的前驱
	{
             p->next->prio = p;连接后继的前驱
	}

	return true;

}



尾插法:操作过程与头插一样,但要先找到尾节点。
bool Insert_tail(DList plist,int val)//尾插
{
	DNode *p = (DNode *)malloc(sizeof(DNode));
	p->data = val;
	DNode *q;	
	for(q=plist;q->next != NULL;q=q->next);
	p->next = q->next;//****
	q->next = p;
	q->prio = plist;
	if(p->next != NULL)
	{
		p->next->prio = p;
	}
	return true;
}
获得链表长度:
int GetLength(DList plist)
{
	DNode *p;
	int count = 0;//计数器
	for(p=plist;p->next != NULL;p=p->next)
	{
		count++;
		
	}
	return count;
}
查找节点:
DNode *Search(DList plist,int key)
{
	DNode *p;
	for(p=plist;p->next!= NULL;p=p->next)//遍历找key		
                  if(p->data == key)
		{
			return p;
		}
		
	}
	return NULL;
}

删除节点:可以利用查找函数,找到之后free它

bool Delete(DList plist,int key)
{
	DNode *p;
	p = Search(plist,key);
	if(p == NULL) //d等于空说明没有找到
	{

	    return false;
	}
	p->prio->next = p->next;//穿过它,将它前一个节点的下一个节点给它的下一个节点

	if(p->next != NULL)  
	{
		p->next->prio = p->prio;//如果后面还有数据,将它的后面也处理好(将后继的前驱制成自己)
	}
		free(p);
		return true;

}  

销毁:

void Destroy(DList plist)
{
	DNode *p;
	while(plist->next!= plist->prio)
	{
		p = plist->next;
		plist->next = p->next;
		free(p);
	}
}
程序测试:

#include<stdio.h>
#include"dlist.h"
#include<vld.h>

int main()
{
	DNode sa;
	InitList(&sa);
	int i;
	for(i=0;i<10;i++)
	{
		Insert_head(&sa,i );

	}
	Show(&sa);
	printf("%d\n",GetLength(&sa));
	Delete(&sa,1);
	Delete(&sa,2);
	Delete(&sa,4);
	Delete(&sa,9);

	//Destroy(&sa);
	//Destroy(&sa);
	//Destroy(&sa);
	Show(&sa);
	printf("%d\n",Search(&sa,7));

}
运行结果:











 

猜你喜欢

转载自blog.csdn.net/lixin_com/article/details/77962748