C++单链表相关操作

链表简介

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,链表比较方便插入和删除操作。

类结构要素

class List {
public:
	List() {
		create_List();
	}
	~List() {
		clear();
	}
	//打印
	void print() {
		for (Node * p = head->next; p; p = p->next) {
			cout << p->data << " ";
		}
		cout << endl;
	}
	
private:
	//节点结构
	struct Node {
		int data;
		Node * next;
		Node(const int& d) : data(d), next(NULL) {

		}
	};

	Node *head;//头节点

	//清理链表函数
	void clear() {
		Node * p = head;
		while (p) {	//从头节点开始循环删除
			Node * q = p->next;
			delete p;
			p = q;
		}
	}
};

基本操作

创建头结点

手动new一个新的Node,将Node的next置为NULL即可。

//创建头结点
void create_List() {	
	head = new Node(0);
}

从头插入一个新的节点

手动new出一个新的节点p,使p的next的指向head->next所指向的地址,然后将head->next从新指向p即可。

//从头插入一个节点
void insert(const int& d) {
	Node *p = new Node(d);
	p->next = head->next;
	head->next = p;
}

删除指定节点

先遍历到指定节点的前一个节点,然后通过将前一个节点的next指针指向指定节点的下一个节点,达到悬空指定节点的效果,然后删除指定节点即可。

//删除指定数据的节点
void erase(const int& d) {
	Node * p = find(d);
	Node *q = p->next;//因为p是上一个节点的位置,用q来保存要删除的节点的地址
	p->next = p->next->next;//通过将上一个节点的next指针指向要删除节点的next实现断开要删除节点的目的
	
	delete q;//删除
}

修改指定节点

遍历到指定节点的位置,将其data修改为要修改的值即可。

//修改指定数据
void updata(const int& d, const int& d1) {
	Node * p = find(d);
	p->next->data = d1;
}

指定节点值后插入节点

查找链表指定值,在该值后插入节点。

//指定位置插入节点
void insert_pos(const int& d, const int& d1)
{
	Node * p = find(d);
	Node * q = new Node(d1);
	q->next = p->next;
	p->next = q;
}

查找指定节点值得前驱节点

指定一个节点值,找到该节点的前面一个节点。

//查找数据d的上一个节点位置的函数,便于后面删除操作
Node* find(const int& d) {
	Node * p = head;
	for (; p; p = p->next) {
		if (p->next->data == d) {
			break;
		}
	}
	return p;
}

进阶操作

反转

步骤:
1、临时保存头节点后的第二个节点q的q->next;
2、q->next指向q的前一个节点;
3、p指针后移以为,q指针后移一位;
重复步骤1-3直到链表尾部。
4、头指针重新指向新的的第1个节点。

//反转链表
void reverse() {
	Node *p = head->next;//头结点之后的第1个节点
	Node *q = head->next->next;//头结点之后的第2节点
	Node *temp;
	p->next = NULL;//将头接点之后的第1个节点的next指针置为空
					   
	while (q->next) {//根据q->next是否为空来判断 以此逆序每一个节点
		temp = q->next;
		q->next = p;
		p = q;
		q = temp;
	}
	q->next = p;//将最后一个节点逆序
	head->next = q;//将头重新指向新的的第1个节点(之前的最后一个节点)
}

反向遍历

从尾部向头部遍历。借助栈,正向遍历,将节点值入栈,最后出栈即可。

//反向遍历
void reversePrint() {
	if (head->next == nullptr) {
		return;
	}
	//创建栈
	stack<int> stack1;
	//遍历指针
	Node *temp = head->next;
	while (temp != nullptr) {
		stack1.push(temp->data);
		temp = temp->next;
	}
	//打印栈中的数据
	while (!stack1.empty()) {
		cout << stack1.top() << " ";
		stack1.pop();
	}
	cout << endl;
}

冒泡排序

节点值交换法
符合条件即交换节点值。

//节点值交换法
void SortVal() {
	Node *p, *q;
	int n_temp = 0;
	for (p = head->next; p != nullptr; p = p->next) {
		for (q = p->next; q != nullptr; q = q->next) {
			if (p->data > q->data)//根据学号从小到大排序
			{
				n_temp = p->data;
				p->data = q->data;
				q->data = n_temp;
			}
		}
	}
}

节点交换法
符合条件即交换节点,交换分两种情况:
1、两个节点不相邻;
2、两个节点相邻。
交换思想:先临时保存后一个节点p的p->next,再交换两个节点即可。

void Sort() {
	Node *p, *q, *p_temp;
	Node *p_pre = head, *q_pre = head->next;
	for (p = head->next; p != nullptr; p = p->next) {
		for (q = p->next; q != nullptr; q = q->next) {
			if (p->data > q->data && p->next != q) {	//p,q节点不相邻
				p_temp = q->next;
				p_pre->next = q;
				q->next = p->next;
				q_pre->next = p;
				p->next = p_pre;
			}
			else if (p->data > q->data && p->next == q) {	//p,q节点相邻
				p_temp = q->next;
				p_pre->next = q;
				q->next = p;
				p->next = p_temp;
			}
			q_pre = q;
		}
		p_pre = p;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值