数据结构之线性表【1】

线性表一般分为顺序表和链表,本篇是对顺序表的回顾,以C++创建简单学生健康管理系统为例。

顺序表是线性表基于数组的存储表示。其定义是:将线性表中的所有项,根据其逻辑顺序(有序或无序皆可),依次存储到一片连续的空间里面,空间的开始位置会被指定好(一般实际起始位置在运行时分配)。

1.顺序表节点的结构体定义:

struct student
{
public:
	int node;
	string name;
	string sex;
	string birthday;
	string health;
};
2.顺序表的类定义:

class seqlist
{
protected:
	student *data;              //指针的形式
	int maxSize;                //初始化时顺序表的最大长度
	int last;                  //当前最后一个节点的标号
public:
	seqlist();                  //构造函数
	~seqlist() { delete[] data; }     //析构函数
	int length() { return last + 1; } const  //此处的 const 表示该函数不能修改类的数据成员
	void Search(int nodes);        //查找表中的某一项
	
	bool insertdata(int i, student& stu);     //插入数据(传入引用以实现修改实参)
	bool removedata(int i);           //删除某一项
	void input();          //初始化输入
	void readdata();       //从文件中读取
	void wridata();       //写入文件
	void output();        //输出整个顺序表
};
3.各函数的具体实现

seqlist::seqlist()
{
	maxSize = 60;
	last = -1;
	data = new student[maxSize];             //初始化分配空间
	/*datas = new students[maxSize];*/
	if (data == NULL)
	{
		cerr << "存储分配错误!" << endl;
	}
}

void seqlist::input()
{
	int i = -1;
	cout << "--------------请按顺序输入初始学生信息(学号 姓名 性别 生日 健康情况):---------------" << endl;
	cout << "--------------------输入学号为任意负数则停止输入,最大数量为60-------------------------" << endl;
	do
	{
		i++;
		cin >> data[i].node >> data[i].name >> data[i].sex >> data[i].birthday >> data[i].health;
		last = i - 1;
	} while ((data[i].node >= 0) && (i <= maxSize - 1));

}

void seqlist::Search(int nodes)
{
	int i = 0;
	for (i = 0;i <= last;i++)
	{
		if (data[i].node == nodes)
		{
			cout << data[i].node << "  " << data[i].name << "  " << data[i].sex 
                             << "  " << data[i].birthday << "  " << data[i].health << endl;
			i = i + 1;
		}
	}
	if (i == 0)
	{
		cout << "查无此人!请检查之后重新输入" << endl;
	}
}

bool seqlist::insertdata(int i, student& stu)     //插入时先检查当前表的大小,及插入位置的合法性
{                                             
	if (last == maxSize - 1) return false;
	if (i<0 || i>last + 1) return false;
	for (int j = last;j >= i;j--)                 //插入时要将插入位置之后的全部后退一个位置 
	{                                            //注意从last开始
		data[j + 1].node = data[j].node;
		data[j + 1].name = data[j].name;
		data[j + 1].birthday = data[j].birthday;
		data[j + 1].sex = data[j].sex;
		data[j + 1].health = data[j].health;
	}
	data[i].node = stu.node;
	data[i].name = stu.name;
	data[i].birthday = stu.birthday;
	data[i].sex = stu.sex;
	data[i].health = stu.health;
	last++;
	return true;
}

bool seqlist::removedata(int i)                 //同理删除某一项时,先检查
{
	if (last == -1)return false;
	if (i<1 || i>last + 1) return false;
	for (int j = i;j <= last;j++)        //删除时直接用删除位置后面的覆盖前面的(实际中应该不能这样)
      {                                     //注意从i开始
		data[j - 1].node = data[j].node;
		data[j - 1].name = data[j].name;
		data[j - 1].birthday = data[j].birthday;
		data[j - 1].sex = data[j].sex;
		data[j - 1].health = data[j].health;
	}
	last--;
	return true;
}

void seqlist::readdata()
{
	student restd; 
	ifstream file;                     //文件流
	file.open("data.txt", ios::in);      //打开
	for (int i = 0;i <= last;i++)
	{
		file >> data[i].node >> data[i].name >> data[i].sex >> data[i].birthday >> data[i].health;
	}
	file.close();
	output();
}

void seqlist::wridata()
{
	fstream file;
	file.open("data.txt", ios::out);
	for (int i = 0;i <= last;i++)
	{
		file.write((char *)& data[i], sizeof(data[i]));
	}
	file.close();
}

void seqlist::output()
{
	for (int i = 0;i <= last;i++)
	{
		cout << data[i].node << "  " << data[i].name << "  " << data[i].sex << "  " 
                     << data[i].birthday << "  " << data[i].health << endl;
	}
}
4.对顺序表的解析:

(1)已知数据在顺序表中的节点位置时,要得到该数据十分容易,直接用数组下标即可

(2)当不知到数据的位置,进行搜索时,则要对每个节点逐个进行比较,这时平均要比较(n+1)/2个表项

(3)当要插入数据时,需要将插入位置之后的每一项都后移一个位置,整体来说平均要移动n/2个表项

(4)当要删除数据时,与插入同理,改向后移动为向前移动即可,平均移动(n-1)/2个表项

总体来说:顺序表是易查找(已知位置时),难修改的,或者说修改顺序表的时间复杂度较高,它需要一片连续的空间。因此,顺序表不适用于插入或删除频繁的情况,也不适合存储空间需求不定的情况。下一章为链表,与顺序表恰好相对应。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值