数据结构4:线性表的应用(1)——单链表的排序与分割

74 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

相关文章

数据结构1:线性表 - 掘金 (juejin.cn)

基础知识

  • 线性表
    • 定义:线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
    • 存储形式:顺序存储(数组实现)、链式存储(链表实现) 在这里插入图片描述

题目

  • 用随机函数生成10个3位整数(100~999),把这些整数存于单链表中,然后读入一个整数,以该值为基准把单链表分割为两部分,所有小于该值的结点排在大于或等于该值的结点之前。

思路

①实现单链表的常规操作:插入结点、链表判空、打印链表操作

②在上述操作的基础上,根据题目要求,遍历链表,比较结点大小,交互结点的数据,从而实现要求的链表分割功能

代码

#include <iostream>
#include <ctime>
using namespace std;


//======================================单链表============================================
class ListNode
{
public:
	ListNode() :data(-1), next(NULL) {}
	ListNode(int m_data, ListNode* m_next = NULL) :data(m_data), next(m_next) {}
	~ListNode() { next = NULL; }   //注意:此处不能写成delet next,否则会导致链表在删除结点时把链表后面的所有结点的指针丢失!!!
public:
	int data;
	ListNode* next;
};

class SingleList
{
public:
	SingleList() :head(new ListNode()), len(0) {}
	~SingleList() {}
	void ListEmpty();
	bool ListInsert(int item, int n);
	void ListDivision(int base);
	void ListPrint();
public:
	ListNode* head;
	int len;
};
void SingleList::ListEmpty()
{
	ListNode* p;
	while (head->next != NULL)
	{
		p = head->next;
		head->next = p->next;
		delete p;
	}
}
bool SingleList::ListInsert(int item, int n)  //插入item,位置n
{
	if (n <= 0 || n > len + 1)  // //链表下标从1开始
	{
		cout << "插入的位置非法!\n";
		return 0;
	}
	ListNode *pmove = head;
	ListNode *pnode = new ListNode(item);
	for (int i = 1; i < n && pmove; i++)  //移动指针到插入位置n的前一个位置n-1
	{
		pmove = pmove->next;
	}
	len++;
	pnode->next = pmove->next;  //插入的结点的next指向原来位置n的结点
	pmove->next = pnode;  //结点n-1的next指向新增结点
	cout << "在第" << n << "位插入" << item << "成功!\n";
	return 1;
}

void SingleList::ListDivision(int base)
{
	SingleList* newList = new SingleList();
	newList->ListInsert(base, 1);  //插入基准结点
	ListNode* basePrePos = newList->head;  //获取基准位置的前一个结点的指针,basePrePos->next为base的指针
	ListNode *pmove = head->next;
	for (int pos = 1; pos <= len; ++pos)  //遍历读取原链表元素
	{
		int item = pmove->data;
		pmove = pmove->next;
		if (item < base)
		{
			ListNode* newNode = new ListNode(item);
			newNode->next = basePrePos->next;
			basePrePos->next = newNode;  //注意这两行代码,否则会造成原本的结点丢失
			basePrePos = newNode;
		}
		else
		{
			ListNode* newNode = new ListNode(item);
			newNode->next = basePrePos->next->next;
			basePrePos->next->next = newNode;
		}
	}
	newList->ListPrint();
	cout << "删除基准结点...\n";
	ListNode* pp = newList->head;
	while (pp->next != NULL)
	{
		if (pp->next->data == base)
		{
			ListNode* tmp = pp->next;
			pp->next = pp->next->next;
			delete tmp;
			break;
		}
		pp = pp->next;
	}
	//打印链表
	newList->ListPrint();

	cout << "链表分割完成!" << endl;
}

void SingleList::ListPrint()
{
	ListNode* p = head->next;
	if (p == NULL) cout << "链表为空!" << endl;
	else
	{
		cout << "链表元素为:Start";
		while (p != NULL)
		{
			cout << "->" << p->data;
			p = p->next;
		}
		cout << "->End" << endl;
	}
}

//=====================测试1======================
void test1()
{
	cout << "=====================测试1 单链表操作======================\n";
	time_t t;
	srand((unsigned)time(&t));
	SingleList Slist;  //定义一个单链表
	for (int i = 1; i <= 10; i++)  //生成10个随机整数存入链表
	{
		Slist.ListInsert(rand() % 900 + 100, i);  //插入到位置i100-999随机整数
	}
	Slist.ListPrint();
	int base;
	cout << "\n执行分割链表的操作...\n";
	cout << "请输入基准整数:";
	cin >> base;
	Slist.ListDivision(base);

结果

在这里插入图片描述