双向循环链表的实现


文章目录

  • 一、双向链表的实现

  • 二、顺序表与链表的区别


一、双向链表的实现

1.双向链表的创建

typedef int LTDataType;
typedef struct ListNode
{
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}LTNode;

2.创建节点

LTNode* BuyListNode(LTDataType x)
{
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	node->data = x;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

3.初始化

LTNode* ListInit()
{
	LTNode* phead = BuyListNode(-1);
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

4.尾插

void ListPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyListNode(x);
	LTNode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

5.尾删

void ListPopBack(LTNode* phead)
{
	assert(phead);

	assert(!ListEmpty(phead));

	LTNode* tail = phead->prev;
	LTNode* tailPrev = tail->prev;

	free(tail);

	tailPrev->next = phead;
	phead->prev = tailPrev;

}

6.头插

void ListPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);

	LTNode* newnode = BuyListNode(x);
	LTNode* next = phead->next;

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

7.头删

void ListPopFront(LTNode* phead)
{
	assert(phead);
	assert(!ListEmpty(phead));

	LTNode* next = phead->next;
	LTNode* Next = next->next;

	phead->next = Next;
	Next->prev = phead;
	free(next);
	
}

8.销毁

void ListDestory(LTNode* phead)
{
	LTNode* cur = phead->next;

	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

9.查找

LTNode* ListFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead;
	
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;

}

10.打印

void ListPrint(LTNode* phead)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

 11.判断链表是否为空

bool ListEmpty(LTNode* phead)
{
	assert(phead);

	return phead->next == phead;
}

12.在指定位置上插入

// 在pos位置之前插入x
void ListInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* prev = pos->prev;
	LTNode* newnode = BuyListNode(x);

	// prve newnode pos
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

13.在指定位置上删除

//  删除pos位置的节点
void ListErase(LTNode* pos)
{
	assert(pos);
	LTNode* prev = pos->prev;
	LTNode* next = pos->next;

	prev->next = next;
	next->prev = prev;
	free(pos);
}

14.求链表的长度

int ListSize(LTNode* phead)
{
	assert(phead);

	int length = 0;
	LTNode* cur = phead->next;
	while (cur != phead) {
		length++;
		cur = cur->next;
	}
	return length;
}

二、顺序表与链表的区别

顺序表的优点:支持随机访问     缓存利用率

顺序表的缺点:头部或者中间插入删除效率低、扩容(有一定的性能消耗,可能存在一定程度的空间浪费)。

缓存利用率高

链表的优点:在任何位置插入删除为O(1),按需申请释放。

链表的缺点:不支持下标的随机访问。

缓存利用率低

注意:数据结构是在内存中增删查改。

三、关于双向链表的题目

复制带随机指针的链表OJ链接

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
public:
    Node* copyRandomList(Node* head) {
        Node*cur=head;
        //第一步将原链表拷贝
        while(cur)
        {
            Node*copy=new Node(cur->val,cur->next);
            cur->next=copy;
            cur=copy->next;
        }
        cur=head;
        //第二步将链表进行改变random指针
        while(cur)
        {
            Node*copy=cur->next;
            if(cur->random==nullptr)
            {
                copy->random=nullptr;

            }
            else
            {
                copy->random=cur->random->next;
            }
            cur=copy->next;
        }
        cur=head;
        Node*copyhead=nullptr,*copytail=nullptr;
        //第三步将链表尾插到新的链表中
        while(cur)
        {
            Node*copy=cur->next;
            Node*next=copy->next;
            if(copytail==nullptr)
               copyhead=copytail=copy;
            else
            {
                copytail->next=copy;
                copytail=copytail->next;
            }
            cur->next=next;
            cur=next;
            
        }
        return copyhead;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

‘(尐儍苽-℡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值