C++学习笔记——链表(一)

发布于:2023-01-04 ⋅ 阅读:(1502) ⋅ 点赞:(1)

链表

什么是链表?

百度百科显示如下:
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

简化理解下:
链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

链表分为:单链表、双链表、单向循环链表、双向循环链表
本文是对单向链表学习的一些基本操作

链表结构体的创建


struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};

链表的初始化


int main(int argc, char *argv[])
{
    ListNode *head = new ListNode(0);
    return (0);
}

链表的元素添加——(在结尾添加)


void add_list(ListNode* head, int val)
{
    ListNode* pNew = new ListNode(val);
    if(head == nullptr)
        head = pNew;
    else
    {
        ListNode* node = head;
        while(node->next != nullptr)
            node = node->next;
        node->next = pNew;
    }
    //head->val++;
}

链表的打印输出

循环遍历输出


void printf_list(ListNode *head)
{
    struct ListNode *temp;
    temp = head;
    while (1)
    if(temp != nullptr){
        cout << temp->val;
        temp = temp->next;      
    }else break;
    cout << "" << endl;
}

链表的创建

创建含有n个节点的链表


ListNode* creat_list(int n) 
{
	ListNode* head = new ListNode(0);
	ListNode* node;
	ListNode* end;
	end = head;
	for (int i = 1; i <= n; i++) 
    {
		node = new ListNode(i);//存放数据
		end->next = node;
		end = node;
		//靠end的移动来创建链表
	}
    head->val = n;//头节点不存放数据,记录节点个数
	return head;//头指针表示一个链表
}

链表的销毁

销毁head链表(留下表头)


ListNode* destroy_list(ListNode* head) 
{
	ListNode* node = head->next;
	ListNode* p = 0;
	while (node) {
		p = node;
		node = node->next;
		delete p;
	}
	head->val = 0;
}

链表查找数值

查找head链表中有无值k,注意要初始化结构体指针为0


ListNode* find_list(ListNode* head, int k)
{
	ListNode* temp = head->next;
	ListNode* p=0;
	while (temp && k != temp->val) {
		p = temp;//保留原节点
		temp = temp->next;
	}
	if (temp == 0)
		return 0;
	return temp;
}

链表查找节点

返回倒数k个节点


ListNode* find_Kcountdown(ListNode* head, int k)
{
	ListNode* fast = head;
	ListNode* slow = head;
	//快指针先行k步 fast-template
	for(int i = 0; i < k; i++){
		if(fast != NULL)
			fast = fast->next;
		//达不到k步说明链表过短,没有倒数k
		else
			return slow = NULL;
	}
	//快慢指针同步,快指针先到底,慢指针指向倒数第k个
	while(fast != NULL){
		fast = fast->next;
		slow = slow->next;
	}
	return slow;
}

链表的节点插入

在第k个节点后插入data,支持尾插(不传k的值)和头插(k=0)


ListNode* insert_list(ListNode* head, int data, int k) 
{
	ListNode* node = head->next;
	ListNode* p = head;
	int  count = 0;
	while(node&&count++!=k){
		p = node;
		node = node->next;
	}
	ListNode* temp = new ListNode(data);
	temp->val = data;
	p->next = temp;
	temp->next = node;
	head->val++;
	return head;
}

链表的节点删除

删除第k个节点
删除倒数第k个节点

//删除第k个节点
ListNode* delete_node(ListNode* head, int k)
{
	ListNode* node = head->next;
	ListNode* p=0;
	for (int i = 1; i < k; i++) {
		p = node;
		node = node->next;
	}
	p->next = node->next;
	delete node;
	head->val--;
	return head;
}

// 删除倒数第k个节点
ListNode* delete_Nend(ListNode* head, int k)
{ 
	//添加表头 fast-template
	ListNode* res = new ListNode(-1);
	res->next = head;
	//当前节点
	ListNode* cur = head;
	//前序节点
	ListNode* pre = res;
	ListNode* fast = head;
	//快指针先行n步
	while(k--)
		fast = fast->next;
	//快慢指针同步,快指针到达末尾,慢指针就到了倒数第n个位置
	while(fast != NULL){
		fast = fast->next;
		pre = cur;
		cur = cur->next;
	}
	//删除该位置的节点
	pre->next = cur->next;
	//返回去掉头
	return res->next;
}


网站公告

今日签到

点亮在社区的每一天
去签到