关于C++如何将数组转化成链表结构并进行链表相关操作的方法

关于C++如何将数组转化成链表结构并进行链表相关操作的方法

定义链表结构体

struct ListNode
{ 
	int val;
	ListNode *next;
	ListNode(int val1, ListNode *next1 = nullptr)
	{ 
		val = val1;
		next = next1;
	}
};

定义创建链表类

class List
{ 
public:
	ListNode *numberList;
	List()
	{ 
		numberList = nullptr;
	}
	~List()
	{ 
		ListNode *n;
		while (numberList != nullptr)
		{ 
			n = numberList;
			numberList = numberList->next;
			delete n;
		}
		cout << "congradgulations!" << endl;
	}

	ListNode *creat(int array[], int len)
	{ 

		for (int i = 0;i < len;i++)
		{ 
			numberList = new ListNode(array[i], numberList);
		}
		return numberList;
	}
	void print()
	{ 
		ListNode *nm = numberList;
		while (nm != nullptr)
		{ 
			cout << nm->val << endl;
			nm = nm->next;
		}
		cout << "hello" << endl;
	}
};

在主函数中建立数组,并通过指针函数*creat给数组成员创建链表,这样就实现了链表的快捷创建。

其中需要注意打印函数print()中需要创建一个新指针来遍历链表节点,防止头指针指向空,调用的时候出现空指针的错误。

书写头文件

头文件一般书写函数的声明、类定义,为了防止重定义错误,头文件开头需要写#pragma once或者#ifndef LISTNODE_H
#define LISTNODE_H

#endif
在头文件中类的成员函数需要写在类里面,这时,编译器将成员函数当作内联函数处理,避免了重定义的错误。

#pragma once
#ifndef LISTNODE_H
#define LISTNODE_H
using namespace std;
struct ListNode
{ 
	int val;
	ListNode *next;
	ListNode(int val1, ListNode *next1 = nullptr)
	{ 
		val = val1;
		next = next1;
	}
};
class List
{ 
public:
	ListNode *numberList;
	List()//构造函数
	{ 
		numberList = nullptr;
	}
	~List()//析构函数
	{ 
		ListNode *n;
		while (numberList != nullptr)
		{ 
			n = numberList;
			numberList = numberList->next;
			delete n;
		}
		cout << "congradgulations!" << endl;
	}

	ListNode *creat(int array[], int len)
	{ 

		for (int i = 0;i < len;i++)
		{ 
			numberList = new ListNode(array[i], numberList);//链表节点的地址和数组中的地址有关系吗
		}
		return numberList;
	}
	void print()
	{ 
		ListNode *nm = numberList;
		while (nm != nullptr)
		{ 
			cout << nm->val << endl;
			nm = nm->next;
		}
		cout << "hello" << endl;
	}
};
class Solution { 
public:
	ListNode* removeElements(ListNode* head, int val)
	{ 
		ListNode* dummyHead = new ListNode(0);
		dummyHead->next = head;
		ListNode* cur = dummyHead;
		while (cur->next != NULL) { 
			if (cur->next->val == val) { 
				ListNode* tmp = cur->next;
				cur->next = cur->next->next;
				delete tmp;
			}
			else { 
				cur = cur->next;
			}
		}
		head = dummyHead->next;
		delete dummyHead;
		return head;
	}
};
void creat(int array[], int len);
void print();
struct ListNode;
class List;
ListNode* removeElements(ListNode* head, int val);


#endif


其中Solution类实现链表指定节点删除,其中用到了链表的虚表头指针,更方便对链表头进行操作。

源文件与main函数

#include<iostream>
#include"ListNode.h"
using namespace std;
//ListNode* removeElements(ListNode* head, int val);

int main()
{ 
	List *l=new List();
	Solution s;
	int a[] = {  1,2,3,4,5,6 };
	int len = sizeof(a) / sizeof(int);
	ListNode *number = l->creat(a, len);
	s.removeElements(number, 3);
	l->print();
	delete l;
	system("pause");
	return 0;
}

在源文件中包含头文件,并调用函数,实现链表操作。

其中sizeof运算符返回一条表达式或一个类型名字所占的字节数,这里通过int len = sizeof(a) /sizeof(int);返回数组a的长度。

输出结果

《关于C++如何将数组转化成链表结构并进行链表相关操作的方法》

将数组a[]={1,2,3,4,5,6}转化为链表结构,并删除值为3的节点,其中hello表示调用了print()函数,congradgulations!表示调用了析构函数。

注意:此处的链表插入方式是从头插入,因此链表头的值是数组的尾部成员。

new与delete

*creat()函数中使用了new命令在堆区创建了空间,由于堆区的空间需要手动创建和手动释放,因此我们需要使用delete来调用析构函数,否则会造成内存泄漏错误。

同时需要注意,delete的使用一般放在程序的末端,因为delete l,也相当于删除了l这个对象。

初学C++的感想

由于之前学过JAVA,现在学起C++感觉C++的语言比较繁琐,但是很灵活、基础,对编程的原理能够很清楚。其中指针是C++的灵魂,指针的灵活应用与管理是我后期需要学习的。

由于C++使用指针,涉及到内存空间,因此C++比JAVA更加灵活也更加危险。

通过这个想法的实现,让我对指针有了更深刻的认识。

    原文作者:wolf-tl
    原文地址: https://blog.csdn.net/weixin_43716907/article/details/121180549
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞