【数据结构】-排序-基于单链表的简单选择排序

本文介绍了如何在单链表上实现简单选择排序。首先,详细解释了不改变链表结构,仅交换节点data值的方法。接着,讨论了题目的实际需求,即需要进行断链插入操作。为此,提出了通过找到每趟最大值并使用头插法将其插入新链表的方法,并强调了编程过程中需要注意的指针管理和链表操作细节。
摘要由CSDN通过智能技术生成

方法一:不进行任何断链插入操作,找到目标节点之后,只是交换data值,这个思路很简单,与简单选择排序的思路一摸一样。


编程注意事项:

min不能标记最小值,应该要标记最小值对应的链表节点

LinkList createLink(LinkList L) {
	cout << "尾插法创建单链表:"<<endl;
	int a;
	L = (LinkList)malloc(sizeof(LinkNode));
	L->next = NULL;
	LinkNode *p=L,*r = L;
	while (true)
	{
		cin >> a;	
		p = (LinkList)malloc(sizeof(LinkNode));
		p->data = a;
		r->next = p;
		r = p;
		if (cin.get() == '\n')break;
	}
	r->next = NULL;
	return L;
}

void printList(LinkList L) {
	LinkNode *p = L->next;
	while (p)
	{
		cout << p->data << " ";
		p = p->next;
	}
}

LinkList sortList(LinkList L) {
	LinkNode* p = L->next;
	LinkNode* q;
	LinkNode* min;
	int temp;
	while (p)
	{
		min = p;//有序序列中的最后位置元素节点
		q = p->next;
		while (q)
		{
			if (min->data > q->data)min=q;
			q = q->next;//寻找无序序列中的最小值节点
		}

		if (min!= p) {//交换data值
			temp = min->data;
			min->data = p->data;
			p->data = temp;
		}
		p = p->next;
	}
	return L;
}

int main() {
	//基于单链表的简单选择排序
	LinkList L=NULL;
	L=createLink(L);
	L = sortList(L);
	cout << endl;
	printList(L);
}

但是,再一次审题:在基于单链表表示的待排序关键字序列上进行简单选择排序,题目想要我们有断链插入操作,而不是直接修改data值,因此,还需要思考另一种方法。

方法二:

思路:每一趟找到未排序序列中的最大值,然后把最大值用头插法插入入新的单链表的首部,既然有插入和删除节点的操作,所以必然需要有指针来标记前驱节点,我们引入两个前驱:pre代表遍历的时候的前驱,pre_max代表目标最大值的前驱。

编程注意事项:

1.在存储了单链表的第一个节点之后,马上把头结点断开,为新的单链表做准备,很多关于单链表的题目都有这个步骤:断开头结点!!否则指针绝对会出错。

2.只有在未排序序列的首部节点已经是最大值节点的时候才需要移动外循环的标记指针,具体可以看下图的实现过程。


LinkList sortList02(LinkList L) {
	//每次找到最大的插入到链表的最前端
	LinkNode* h = L->next;
	LinkNode* max, *p, *pre, *pre_max;
	L->next = NULL;
	while (h)
	{
		max=p= h;
		pre =pre_max = NULL;
		while (p)
		{
			if (p->data > max->data) {
				pre_max = pre;
				max = p;
			}
				pre = p;
				p = p->next;
	
		}
		//将max插入到头结点之后,并保持单链表链接
		if (max == h) h = h->next;		
		else 
			pre_max->next = max->next;

		max->next = L->next;
		L->next = max;	
	}

	return L;
}

 

链表简单选择排序实现起来相对简单,具体步骤如下: 1. 定义一个指向链表头结点的指针p,初始值为链表头结点。 2. 定义一个指向链表节点的指针minp,初始值为p。 3. 从p开始遍历整个链表,找到链表中最小的节点,将其指针赋给minp。 4. 将minp指向的节点与p指向的节点进行交换。 5. 将p指针指向下一个节点。 6. 重复步骤2~5,直到链表中的所有节点都被遍历完毕。 以下是基于链表简单选择排序的实现代码: ```c++ #include <iostream> using namespace std; struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; void selectionSort(ListNode* head) { ListNode* p = head; while (p != NULL) { ListNode* minp = p; ListNode* q = p->next; while (q != NULL) { if (q->val < minp->val) minp = q; q = q->next; } swap(p->val, minp->val); p = p->next; } } int main() { // 构造测试链表 ListNode* head = new ListNode(3); head->next = new ListNode(1); head->next->next = new ListNode(4); head->next->next->next = new ListNode(2); // 遍历测试链表 cout << "Before sorting: "; ListNode* p = head; while (p != NULL) { cout << p->val << " "; p = p->next; } cout << endl; // 对测试链表进行简单选择排序 selectionSort(head); // 遍历排序后的链表 cout << "After sorting: "; p = head; while (p != NULL) { cout << p->val << " "; p = p->next; } cout << endl; // 释放链表内存 while (head != NULL) { ListNode* p = head; head = head->next; delete p; } return 0; } ``` 输出结果为: ``` Before sorting: 3 1 4 2 After sorting: 1 2 3 4 ```
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vector<>

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值