双向链表的基本操作

1. 与双向链表的初相识

首先,要明白它长什么样子:

双向链表的基本操作

  通过观察可以发现这玩意由好几个单体组成,长度不定。欸嘿嘿,但每一个单体都是一样的啊。

————有数据,有指向上一个单体的指针,有指向下一个单体的指针,只不过首尾指向空而已。

那么这几行代码就不南个理解啦!

typedef struct Node
{
	int data;//节点里存储的数据
	struct Node* front;//指向前一个单体的指针
	struct Node* tail; //指向后一个单体的指针
}NODE,*LPNODE;

创建一个节点就更好理解喽

LPNODE createNode(int data) 
{
	LPNODE newNode = (LPNODE)malloc(sizeof(NODE));//new一个节点
	assert(newNode);//断言,万一没有new出来就终止
	newNode->front = NULL;//就创建了一个节点,首尾指向空
	newNode->tail = NULL;
	newNode->data = data;//传数据
	return newNode;
}

其次,我们要处理的是一个双向链表,并不是一个一个的节点,那是不是得创建一个双像链表的结构呢?必须滴。

typedef struct DList 
{
	LPNODE frontNode; //双向链表的首节点
	LPNODE tailNode;  //双向链表的尾节点
	int curSize;      //当前链表列表有多少个节点
}DLIST,*LPDLIST;
LPDLIST createDList() //创建一个双向链表
{
	LPDLIST list = (LPDLIST)malloc(sizeof(DLIST));
	assert(list);
	list->frontNode = NULL;
	list->tailNode = NULL;
	list->curSize = 0;
	return list;
}

好啦下面进入插入删除操作啦;

   头部插入:

void push_front(LPDLIST list,int data) 
{
	if (list == NULL)//判断列表是否为NULL,NULL和’空‘两个意思哦
		return;
	LPNODE newNode = createNode(data);//先创建一个再插入啊
	if (list->curSize == 0)           //如果是空链表
	{
		list->frontNode = newNode;    //列表的头节点就是创建的那个
		list->tailNode = newNode;     //欸嘿嘿,尾节点也是它哦
		list->curSize++;              //插入了嘛,节点数就变了+1
	}
	else                              //如果不是空链表
	{
		newNode->tail = list->frontNode; //先创建的节点的尾部指向列表的头节点
		list->frontNode->front = newNode;//列表的头节点的指向下一个节点的指针指向新创建的节点
		list->frontNode = newNode;       //列表的头节点变成了新创建的节点
		list->curSize++;                 //插入了嘛,节点数就变了+1
	}
}

对于不是NULL节点插入的图像:         我画的不好看哈,将就着看吧。。。三步走

双向链表的基本操作

 尾部插入:

void push_back(LPDLIST list, int data) 
{
	if (list == NULL)//判断是否为NULL链表
		return;
	LPNODE newNode = createNode(data);//创建节点
	if (list->curSize == 0)           //如果为空链表,就。和头部插入一样了
	{
		list->frontNode = newNode;
		list->tailNode = newNode;
		list->curSize++;
	}
	else                             //如果不是
	{
		list->tailNode->tail = newNode;//链表的尾节点的尾部指向新链表
		newNode->front = list->tailNode;//新节点的头指针指向此时链表的尾节点
		list->tailNode = newNode;       //尾节点只有一个,,就是最后一个
		list->curSize++;                //插入了嘛,节点个数+1
	}
}

指定位置插入:  注意注意 这里用数据充当指定位置

void push_appoin(LPDLIST list, int posData, int data) 
{
	if (list == NULL||list->curSize==0)
		return;
	if (list->frontNode->data == posData)
	{
		push_front(list, data);
	}
	else 
	{
		LPNODE preNode = list->frontNode;//要插入的节点的前一个节点
		LPNODE curNode = list->frontNode;//要插入的节点的后一个节点
		while (curNode != NULL && curNode->data != posData) 
		{
			preNode = curNode;
			curNode = preNode->tail;
		}
		if (curNode == NULL) 
		{
			printf("未找到指定位置,无法插入!\n");
		}
		else 
		{
			LPNODE newNode = createNode(data);//创建要插入的节点
			preNode->tail = newNode;//前一个节点的尾指针指向新节点
			newNode->tail = curNode;//新节点的尾指针指向后一个节点
			curNode->front = newNode;//后一个节点的前指针指向新节点
			newNode->front = preNode;//新节点的前指针指向前一个节点
			list->curSize++;
		}
	}
}

双向链表的基本操作

 接下来删除的相应操作就不用多说了吧。

void pop_front(LPDLIST list) 
{
	if (list == NULL || list->curSize == 0) 
	{
		printf("无法删除!链表为空\n");
		return;
	}
	LPNODE nextNode = list->frontNode->tail;  //nextNode=NULL
	free(list->frontNode);
	list->frontNode = nextNode;				  //NULL
	if (nextNode != NULL)
	{
		nextNode->front = NULL;
	}
	else 
	{
		list->tailNode = NULL;
	}
	list->curSize--;
}
void pop_back(LPDLIST list) 
{
	if (list == NULL || list->curSize == 0) 
	{
		printf("链表为空无法删除!\n");
		return;
	}
	LPNODE preNode = list->tailNode->front;	//表尾的上一个节点
	free(list->tailNode);
	list->tailNode = preNode;
	if (preNode != NULL) 
	{
		preNode->tail = NULL;   //当只有一个节点preNode=NULL
	}
	else 
	{
		list->frontNode = NULL;
	}
	list->curSize--;
}
void pop_appoin(LPDLIST list, int posData) 
{
	if (list == NULL || list->curSize == 0) 
	{
		printf("链表为空无法删除!");
		return;
	}
	if (list->frontNode->data == posData) 
	{
		pop_front(list);
		return;
	}
	LPNODE preNode = list->frontNode;
	LPNODE curNode = list->frontNode;
	while (curNode != NULL&&curNode->data!=posData)
	{
		preNode = curNode;
		curNode = preNode->tail;
	}
	if (curNode == NULL)
	{
		printf("未找到指定位置无法删除!\n");
	}
	else 
	{
		if (list->tailNode == curNode) 
		{
			pop_back(list);
		}
		else 
		{
			preNode->tail = curNode->tail;
			//curNode->tail是不是不空
			//当删除的表尾时候,curNode->tail等于空
			curNode->tail->front = preNode;
			free(curNode);
			curNode = NULL;
			list->curSize--;
		}
	}
}

预祝新年快乐!!!

上一篇:高性能计算之MPI:在本地下载、安装、配置、使用MPI


下一篇:easyui 入门