详解双向链表

1.创建一个新的节点的函数

LTNode*BuyLTnode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return NULL;
	}
	newnode->next = NULL;
	newnode->prev = NULL;
	newnode->data = x;
	return newnode;
}

2.哨兵位的两个next,都初始化为了,链接自己的节点的next

 详解双向链表_第1张图片

LTNode* LTInit()
{
	LTNode* phead = BuyLTnode(-1);//这个-1是给哨兵位的data的,把哨兵位data初始化成-1
	phead->next = phead;
	phead->prev = phead ;
	return phead;
}

 

3.尾插先从head->prev,找到最后的一个位置

详解双向链表_第2张图片

void LTPushBack(LTNode* phead, LTDataType x)
{
	//LTInsert(phead, x);
	assert(phead);
	LTNode* tail = phead->prev;
	LTNode* newphead = BuyLTnode(x);
	tail->next = newphead;
	newphead->prev = tail;
	phead->prev = newphead;
	newphead->next = phead;

4.头插,first先记录head的下一个节点,防止插入时把head的下一个节点地址替换弄没了

详解双向链表_第3张图片

 

void LTPushPront(LTNode* phead, LTDataType x)
{
	//LTInsert(phead->next, x);
	assert(phead);
	LTNode* newnode = BuyLTnode(x);
	LTNode* first = phead->next;//注意此步
	//空链表直接在哨兵位插入,为空的情况
	phead->next = newnode;
	newnode->prev = phead;

	//不为空的情况
	newnode->next = first;
	first->prev = newnode;
}

 

5.尾删,phead->prev;找到尾并记录下来并free掉最尾节点,而且还要把尾的前一个节点记录下来记录到new里,再让哨兵位和新的节点new建立新的连接

详解双向链表_第4张图片

 

void LTPopBack(LTNode* phead)
{
	//LTErase(phead->prev);
	assert(phead);
	//没有数据只有哨兵位了,防止删了哨兵位
	assert(!LTEmpty(phead));//bool相同返回来的是真,但在assert括号中!ture,不等于真。bool相同返回为真则判断为假。
	LTNode* tail = phead->prev;
	LTNode* new = tail->prev;
	free(tail);
	new->next = phead;
	phead->prev = new;
}

6.头删把哨兵位后一个节点删掉,且哨兵位和第二节点建立新的连接

详解双向链表_第5张图片

 

void LTPopPront(LTNode* phead)
{
	//LTErase(phead->next);
	assert(phead);
	assert(!LTEmpty(phead));
	LTNode* first = phead->next;
	LTNode* second = first->next;
	free(first);
	phead->next = second;
	second->prev = phead;
}

7.打印函数,从哨兵位的下一个节点开始打印

详解双向链表_第6张图片

 

void LTPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;//注意此步
	printf("sentinel<==>");
	while (cur != phead)
	{
		printf("%d<==>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

8.寻找想查找的的值,pos->data == x就是要查找的节点

详解双向链表_第7张图片

LTNode* LTFind(LTNode* pos, LTDataType x)//寻找想查找的的值
{
	assert(pos);
	LTNode* cur = pos->next;
	while (cur != pos)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

9.在poss处之前插入,在寻找到处的前处插入,first先记录head的下一个节点,防止插入时把head的下一个节点地址替换弄没了,和头插原理相同

详解双向链表_第8张图片

void LTInsert(LTNode* pos, LTDataType x)//在poss处之前插入,在寻找到处的前处插入
{
	assert(pos);
	LTNode* newnode = BuyLTnode(x);
	LTNode* first = pos->prev; 

	pos->prev = newnode;
	newnode->next = pos;

	first->next = newnode;
	newnode->prev = first;
}

 

10.删除poss处的节点

详解双向链表_第9张图片

 

void LTErase(LTNode* pos)//删除poss处的节点
{
	assert(pos);
	LTNode* cur = pos;
	LTNode* tail = pos->next;
	LTNode* first = pos->prev;
	free(cur);
	tail->prev = first;
	first->next = tail;
}

11.删除所有的节点

详解双向链表_第10张图片 

void LTDestroy(LTNode* phead)
{
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;//保存下一个节点
		free(cur);
		cur = next;//下一个节点更新到cur,循环走起来
	}
	free(phead);
}

 

12.布尔值:布尔值:return phead->next == phead;若不相等返回为假,相等返回真。

     12.2.assert(!LTEmpty(phead));assert不等于真。bool函数返回的值假在assert括号中就是真就不会触发assert, bool函数返回值真在assert括号中就是假就触发asser。
    12. 3.为在头删和尾删的函数使用为了防止哨兵位被删掉了
bool LTEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead;//相同返回的真:ture
}

你可能感兴趣的:(链表)