C++:创建链表的过程详解

创建链表的过程详解

本人是一名刚开始学习算法的小白,今天遇到了一些关于链表的创建问题,查了一些资料,我把它们整理了一下,希望大家多多指教。

整体的代码:
#include<iostream>
using namespace std;

struct Node {
	int val;
	Node* next;
};

#创建
Node* creatlist(int n) {
	Node* Head=new Node;    //头节点 不存储数据
	Head->next = NULL;      
	Node* pre = Head;  //指向下一个节点的过渡值
	

	cout << "请依次输入" << n << "个链表的值:";
	for (int i = 0;i < n;i++) {
		Node* temp = new Node;
		cin >> temp->val;

		pre->next = temp;
		pre = temp;
		temp->next = NULL;	
	}
	return Head;
}

#显示
void display(Node* head) {
	Node* temp=head->next;
	int e;
	cout << "该链表的遍历依次为:";
	while (temp!=NULL) {
		e = temp->val;
		cout << e << " ";
		temp = temp->next;
	}
	cout << "\n";
}

int main() {
	int nums;
	cout << "请输入链表的长度:";
	cin >> nums;
	Node* head = creatlist(nums);
	display(head);
	return 0;
}
解释

1、基本概念:
链表是物体存储单元上不连续的储存结构,数据元素是由链表上的指针所连接。
每个节点都包含两部分:存储数据的数据域,和存储下一个节点的地址的指针域。

在这里插入图片描述

根据上图,利用数据结构struct建立一个节点:

struct Node {
	int val;    //数据域
	Node* next;  //指数域
};

创建链表:

#创建
Node* creatlist(int n) {
    //头节点 不存储数据,指针域指向空
	Node* Head=new Node;    
	Head->next = NULL; 
	//为了让节点连接成链接,定义pre,最开始pre等于Head    
	Node* pre = Head;  
	

	cout << "请依次输入" << n << "个链表的值:";
	for (int i = 0;i < n;i++) {
	   //每次循环都创建一个新的节点
		Node* temp = new Node;
		//把值赋给temp节点的数据域
		cin >> temp->val;
        //pre的指数域指向的下一个节点temp,把pre和temp连接起来
		pre->next = temp;
		//把temp节点赋给pre,重新定义pre
		pre = temp;
		//在下次for循环再一次创建新temp节点前,temp的指数域指向空
		temp->next = NULL;	
	}
	//把头节点返回,知道头节点,节点与节点之间又相互连接,所以知道每个节点中的值
	return Head;
}

Node* pre 在这个程序中的作用是将不同节点连接成链接,
最开始pre等于head,pre的指数域指向temp1,然后将temp1赋给pre,temp1的指数域指向空,
下次循环建立temp2,pre的指数域指向temp2,然后将temp2赋给pre,temp2的指数域指向空。

创建链表的关键是要把节点连接起来,也就是要让前一个节点的指针域指向下一个节点:
在这里插入图片描述

显示链表:只要输入链表的头节点,就可以不断通过节点的指向来显示出所有节点的val:

void display(Node* head) {
	Node* temp=head->next;
	int e;
	cout << "该链表的遍历依次为:";
	while (temp!=NULL) {
		e = temp->val;
		cout << e << " ";
		temp = temp->next;
	}
	cout << "\n";
}

习题1:合并两个链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* preHead = new ListNode(-1);

        ListNode* prev = preHead;
        while (l1 != nullptr && l2 != nullptr) {
            if (l1->val < l2->val) {
                prev->next = l1;
                l1 = l1->next;
            } else {
                prev->next = l2;
                l2 = l2->next;
            }
            prev = prev->next;
        }

        // 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
        prev->next = l1 == nullptr ? l2 : l1;

        return preHead->next;
    }
};

习题2:删除链表中的元素

struct Node {
	int data;
	Node* next;
};

int Delete(int i) {          //删除i处的数据
	Node* temp;
	temp = Head;
	int j = 0;
	while (temp && j < i - 1) {
		temp = temp->next;
		j++;
	}
	if (!temp || j > i - 1) {
		cout << "删除位置错误";
		return -1;
	}
	else {
		Node* s;
		s = temp->next;
		temp->next = s->next;
		delete s;
	}
}
 struct ListNode {
     int val;
     ListNode *next;
     ListNode(int x) : val(x), next(NULL) {}
 };
 
 ListNode* deleteDuplicates(ListNode* head) {
            ListNode* pre=head;

            while(pre!=NULL && pre->next!=NULL){
               if(pre->val == pre->next->val){
                 pre->next = pre->next->next;
               }
               else{
                 pre = pre->next;
               }
            }
            return head;
    }

习题3:判断两个链表是否相交

解法一:双指针法

在这里插入图片描述可以理解成两个人速度一致, 走过的路程一致。那么肯定会同一个时间点到达终点。如果到达终点的最后一段路两人都走的话,那么这段路上俩人肯定是肩并肩手牵手的。
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL) {return NULL;}

        ListNode *p1=headA;
        ListNode *p2=headB;
        while(p1!=p2){
            p1= p1==NULL?headB:p1->next;
            p2= p2==NULL?headA:p2->next;
        }
        return p1;
    }
};
解法二:暴力法

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p1=headA;
        ListNode *p2=headB;
        while(p1!=p2){
            p1= p1==NULL?headA:p1->next;
            p2= p2==NULL?headB:p2->next;
        }
        return p1;
    }
};

解法三:哈希表法

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*> set;
        ListNode* hA = headA; ListNode* hB = headB;
        
        while(hA) {
            set.insert(hA);
            hA = hA->next;
        }
        while(hB) {
            if(set.count(hB) == 1) return hB;
            hB = hB->next;
        }
        return NULL;
    }    
};

参考:

链接: 用c++写一个链表

链接: 哔哩哔哩视频

  • 65
    点赞
  • 244
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在C语言中,你可以通过以下方式创建一个链表库函数: 1. 首先,你需要定义一个链表节点的结构体,包含一个整型数据成员和一个指向下一个节点的指针成员。你可以使用引用中提供的结构体定义来创建节点。 2. 接下来,你可以创建一个函数来创建链表。这个函数可以根据用户输入的数据来逐个创建链表节点,并将它们连接起来。你可以使用引用中提供的链表创建函数作为参考。 3. 在创建链表函数中,你需要定义一个头指针来指向链表的第一个节点。在每次创建节点时,你需要判断头指针是否为空。如果为空,说明链表还没有节点,将头指针指向当前创建的节点。如果不为空,说明链表已经有节点了,将前一个节点的next指针指向当前创建的节点。 4. 当用户输入0时,结束创建过程。最后一个节点的next指针应该指向NULL,表示链表的结束。 5. 最后,返回头指针作为创建链表的结果。 以下是一个示例代码来创建链表库函数: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node* next; } Node; Node* CreateList() { Node* head = NULL; Node* p = NULL; Node* s = NULL; s = (Node*)malloc(sizeof(Node)); printf("请输入节点的数据(输入0结束):"); scanf("%d", &(s->data)); while (s->data != 0) { if (head == NULL) { head = s; } else { p->next = s; } p = s; s = (Node*)malloc(sizeof(Node)); printf("请输入节点的数据(输入0结束):"); scanf("%d", &(s->data)); } p->next = NULL; free(s); return head; } ``` 请注意,以上代码仅仅是一个示例,你可以根据自己的需求进行适当的修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值