带头单链表 C++实现

节点定义

带头单链表:我们只需要一个结点指针指向整个链表的第一个节点,这样我们就可以通过next指针访问整个链表内的所有节点

template<class T>
struct ListNode
{
	T _val;
	ListNode* _next;
	
	ListNode(const T &val)
		:_val(val)
		,_next(nullptr)
	{}
};

 这里默认将节点的_next指针设置成nullptr

构造析构函数

 成员变量只需要Node* 的头指针即可,这里的_n用来记录整个链表中有几个节点

初始化将_head赋成nullptr 因为开始是空链表

析构:直接遍历链表中的节点,按顺序删除节点即可

template<class T>
class List
{
public:
	typedef ListNode<T> Node;

	List()
	{
		_head = nullptr;
		_n = 0;
	}

	~List()
	{
		Node* cur = _head;
		while (cur)
		{
			_head = _head->_next;
			delete cur;
			cur = _head;
			--_n;
		}
		_head = nullptr;

	}

private:
	Node* _head;
	size_t _n;
};

插入节点

        push_back

尾插:首先需要找到最后一个节点的地址,将新节点连到最后一个节点的_next上完成尾插

需要考虑_head 为nullptr的情况,因为 为nullptr时找尾操作会访问野指针!

void push_back(const T& val)
{
	Node* newnode = new Node(val);

	if (_head == nullptr)
	{
		_head = newnode;
		_n++;
	}
	else
	{
		Node* cur = _head;
		while (cur->_next)
		{
			cur = cur->_next;
		}
		cur->_next = newnode;
		_n++;
	}
}

        push_front

头插:头插不需要找尾,只需要让新节点指向原链表,头节点_head指向新节点即可

注意还需要考虑_head为nullptr的情况

void push_front(const T& val)
{
	Node* newnode = new Node(val);

    newnode->_next = _head;
	_head = newnode;
	++_n;
}

删除节点

pop_back

这里需要分情况,这里的0个节点的情况作了温柔处理,还可以直接assert暴力处理

有多个节点时,需要找到最后一个节点和最后一个的节点的前一个节点,进行删除操作,并将tailPrev的next指针赋为nullptr 

	void pop_back()
	{
		//①0个节点
		if (_head == nullptr)
		{
			return;
		}
		//②一个节点
		if (_head->_next == nullptr)
		{
			delete _head;
			_head = nullptr;
			--_n;
			return;
		}
		//③一个节点以上
		Node* tail = _head;
		Node* tailPrev = nullptr;
		while (tail->_next)
		{
			tailPrev = tail;
			tail = tail->_next;
		}	
		
		delete tail;
		tail = nullptr;
		tailPrev->_next = nullptr;
		--_n;
	}

pop_front

头删比尾删简单的多:还是这里的空链表情况进行了温柔处理,还可以assert暴力处理

先将_head指向第二个节点,如果只有一个节点的话恰好就是nullptr,然后直接删除_head之前指向的节点 

	void pop_front()
	{
		if (_head == nullptr)
		{
			return;
		}
		Node* deleteNode = _head;
		_head = _head->_next;
		delete deleteNode;
		deleteNode = nullptr;
		--_n;
	}

遍历节点

 根据链表的最后一个节点的next指针是空来判断走到了链表的尽头,挨个打印即可

void print()
{
	Node* cur = _head;
	while (cur)
	{
		cout << cur->_val << "->";
		cur = cur->_next;
	}
	cout << "NULL" << endl;
	cout << "节点数量:" << _n << endl;
}

测试代码

void test1()
{
	List<int> L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	L1.print();
}

void test2()
{
	List<int>L1;
	L1.push_front(10);
	L1.push_front(20);
	L1.push_front(30);
	L1.push_front(40);
	L1.print();

	L1.pop_back();
	L1.pop_back();
	L1.print();
}
void test3()
{
	List<int>L1;
	L1.push_front(10);
	L1.push_front(20);
	L1.push_front(30);
	L1.push_front(40);
	L1.print();

	L1.pop_front();
	L1.pop_front();
	L1.pop_front();
	L1.pop_front();
	L1.pop_front();
	
	L1.print();
}

void test4()
{
	List<int>L1;
	L1.push_front(10);
	L1.push_front(20);
	L1.push_front(30);
	L1.push_front(40);
	L1.print();

	L1.pop_back();
	L1.pop_back();
	L1.pop_back();
	L1.pop_back();
	L1.pop_back();
	L1.pop_back();

	L1.print();
}

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是带头节点单链表实现 c 代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next; } Node; typedef struct List { Node *head; } List; // 初始化带头节点的单链表 void initList(List *list) { list->head = (Node *)malloc(sizeof(Node)); list->head->next = NULL; } // 在链表尾部插入元素 void insert(List *list, int data) { Node *p = list->head; while (p->next != NULL) { p = p->next; } Node *newNode = (Node *)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; p->next = newNode; } // 删除链表中指定元素 void delete(List *list, int data) { Node *p = list->head; while (p->next != NULL) { if (p->next->data == data) { Node *temp = p->next; p->next = temp->next; free(temp); return; } p = p->next; } } // 查找链表中指定元素的位置 int find(List *list, int data) { Node *p = list->head->next; int index = 0; while (p != NULL) { if (p->data == data) { return index; } index++; p = p->next; } return -1; } // 输出链表元素 void printList(List *list) { Node *p = list->head->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { List list; initList(&list); insert(&list, 1); insert(&list, 2); insert(&list, 3); insert(&list, 4); insert(&list, 5); printf("原始链表:"); printList(&list); delete(&list, 3); printf("删除元素 3 后的链表:"); printList(&list); printf("元素 4 在链表中的位置是:%d\n", find(&list, 4)); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值