持续创作,加速成长!这是我参与「掘金日新计划 · 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;
}
}