数据结构1:线性表

156 阅读4分钟

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

基础知识

  • 线性表
    • 定义:线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
    • 实现:线性表主要由顺序表示或链式表示。
    • 应用:在实际应用中,常以栈、队列、字符串等特殊形式使用。
    • 存储形式:顺序存储、链式存储

    顺序表,使用数组实现,一组地址连续的存储单元,数组大小有两种方式指定,一是静态分配,二是动态扩展。

    • 常见的操作:插入结点、删除结点、查找结点、链表反转、打印链表元素、...
    • 单链表的类型:带头结点的链表、不带头结点的链表 在这里插入图片描述

笔者记: 链表是一种重要的数据存储形式,可以动态扩增数据量,不会受限于预先分配的空间大小,正是这一系列的特点,在算法实现、应用开发中得到广泛应用。对于C++初学者以及算法入门者是必须掌握的编码技能!

题目

线性表的链表实现:

(1)用随机函数生成10个3位整数(100~999),把这些整数存于链表中;

(2)输出链表的内容;

(3)读入一个整数,查看该整数是否在表中,若在,输出其位置(首位置为1);

(4)读入一个整数,以及要插入的位置,把该整数插入到链表中,输出链表的内容(要求判断输入的位置是否合理);

(5)读入一个整数,若该整数在链表里,删除该整数,输出链表的内容;

(6)把链表的内容翻转,输出链表的内容。

思路

① 通过定义一个class类 ListNode,表示链表的结点;

② 通过定义一个class类 SingleList ,表示各种链表,封装了对链表的各种操作:

③ 具体实现操作在main()函数中调用执行

代码

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

class ListNode  //链表结点类
{
public:
	ListNode() :data(0), next(NULL) {}  //构造函数:初始化链表
	ListNode(int m_data,ListNode *m_next=NULL):data(m_data),next(m_next){}
	~ListNode() { next = NULL; }  //析构函数:删除指针
	//int getData() { return data; }
	//ListNode* getNext() { return next; }
	int data;
	ListNode *next;
};

class SingleList  //单链表类
{
public:
	SingleList():head(new ListNode()), len(0){}  // 构造函数:初始化头结点和长度
	~SingleList() {
		ListEmpty();  //清空链表
		delete head;  //删除头结点
	}
	void ListEmpty();  //清空链表
	int getLength();  //获得当前链表的长度
	ListNode* getPos(int n);  //获取位置n的指针
	int find(int item);  //在链表中查找元素,返回元素位置
	bool insert(int item,int n);  //在链表位置n中插入元素item,判断插入是否合理
	bool remove(int n);  //删除位置n的数据和指针
	void rollback();  //链表翻转
	void print();  //打印链表
	
private:
	ListNode* head;  //头结点
	int len;  //链表长度
};
void SingleList::ListEmpty()
{
	ListNode *p;   //暂存当前指针
	//从链表头开始,每次读出指针,将头指针指向下一个指针,删除当前指针
	while (head->next != NULL)
	{
		p = head->next;
		head->next = p->next;
		delete p;
	}
}
int SingleList::getLength()
{
	return len;
}
ListNode* SingleList::getPos(int n)
{
	if (n <= 0 || n > len) {
		cout << "输入的下标非法!\n";
		return NULL;
	}
	ListNode *pmove = head->next;
	int pos = 1;
	while (pos != n && pmove) {
		pmove = pmove->next;
		pos++;
	}
	return pmove;
}
int SingleList::find(int item)
{
	int pos = 1;  //链表下标从1开始
	ListNode* pmove = head->next;
	while (pmove&&pmove->data != item)  //指针未到链表尾且当前指针的值不是所查找的值时,继续往后找
	{
		pmove = pmove->next;
		pos++;
	}
	if (pmove == NULL) pos = -1;  //找不到指定数据,返回-1
	return pos;
}
bool SingleList::insert(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;
}
bool SingleList::remove(int n)
{
	if (n <= 0) {
		cout << "输入下标非法!\n";
		exit(1);
	}
	ListNode *pmove = head->next;
	ListNode *pdel;
	for (int i = 1; i < n&&pmove -> next; i++)  //移动指针到插入位置n的前一个位置n-1
	{
		pmove = pmove->next;
	}
	if (pmove->next == NULL) {
		cout << "查找的下标超出链表长度!\n";
		exit(1);
	}
	pdel = pmove->next;  //记录删除结点的指针
	pmove->next = pdel->next;  //结点n-1指向n+1
	delete pdel;
	cout << "删除第" << n << "个结点成功!\n";
	len--;
	return 1;
}
void SingleList::rollback()
{
	for (int i = 1; i <= len / 2; i++)
	{
		ListNode *node1 = getPos(i);  //获取对称为的结点的指针和数据
		ListNode *node2 = getPos(len - i + 1);
		int m_data = node1->data;  //数据交换
		node1->data = node2->data;
		node2->data = m_data;
	}
	cout << "翻转完成!\n";
}
void SingleList::print()
{
	ListNode *pmove = head->next;
	cout << "Head";
	while (pmove) {  //遍历
		cout << "-->" << pmove->data;
		pmove = pmove->next;  //指针后移
	}
	cout << "-->End\n";
}

int main()
{
	time_t t;  //随机种子由时间确定
	srand((unsigned)time(&t));
	SingleList Slist;  //定义一个单链表
	for (int i = 1; i <= 10; i++)  //生成10个随机整数存入链表
	{
		Slist.insert(rand() % 900 + 100, i);  //插入到位置i100-999随机整数
	}
	Slist.print();  //打印显示
	//bool flag;
	int num;
	int pos;
	//=====================测试1=====================
	cout << "读入一个整数,查看该整数是否在表中(请输入三位正整数):";
	cin >> num; 
	pos = Slist.find(num);  //获取查找的数组的位置,找不到返回-1
	if (pos != -1) {
		cout << "查找的数据在链表的第" << pos << "个位置\n";
	}
	else cout << "链表中不存在数字" << num << endl;
	//=====================测试2=====================
	cout << "读入一个整数,以及要插入的位置,把该整数插入到链表中,输出链表的内容(请输入非0整数和插入位置):"<<endl;
	cout << "插入数据:";
	cin >> num;
	cout << "插入位置:";
	cin >> pos;
	Slist.insert(num, pos);
	Slist.print();
	//=====================测试3=====================
	cout << "读入一个整数,若该整数在链表里,删除该整数,输出链表的内容(请输入要查找并删除的整数):";
	cin >> num;
	pos = Slist.find(num);
	if (pos != -1) {
		Slist.remove(pos);
		cout << "删除数字" << num << "成功!\n";
	}
	else cout << "链表中不存在数字" << num << endl;
	Slist.print();
	//=====================测试4=====================
	cout << "是否把链表翻转,请输入数字(否:0;是:other):";
	int choose;
	cin >> choose;
	if (choose == 1) {
		cout << "把链表的内容翻转,输出链表的内容..." << endl;
		Slist.rollback();
		Slist.print();
	}
	else {
		cout << "链表不翻转!"<<endl;
		cout << "实验结束!" << endl;
	}
}

结果

在这里插入图片描述