数据结构之线性表——(一、顺序存储结构)
线性表的逻辑结构
线性表的定义:
- 一种线性存储结构,数据元素“一个接一个地排列”并且元素个数有限。
- 在一个线性表中元素的数据类型是相同的——相同性。
- 线性表是具有相同数据类型的n(n>=0)个元素的有限序列,通常记为: (a2 , a2 , ······,ai-1 , ai , ai+1 , ······ ,an )这时候我们称称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。注:其中n为表长,a=0为空表。
- 我们说“线性”和“非线性”,只在逻辑层次上讨论,而不考虑存储层次,所以双向链表和循环链表依旧是线性表。
线性表的基本操作:
对于不同的应用,线性表的基本操作是不同的,下面是最基本的操作。
- 线性表初始化:Init_List(L)
- 求线性表长度:Length_List(L)
- 取表中的元素:Get_List(L,i,x)
- 按照值去查找:Locate_List(L,x)
- 数值插入操作:Insert_List(L,i,x)
- 数值删除操作:Delete_List(L,i,x)
插入操作初始条件:
-线性表L存在
-插入位置正确(1 <= i <= n,n为插入之前的表长)
插入操作后的结果:
在线性表L的第i个位置上插入一个值为x的新元素,这样会使得原来序号为:i , i+1 , ··· , n 的数据元素的序号变为:i+1 , i+2 , ··· , n+1 ,插入后表长=原表长+1
删除操作初始条件:
-线性表L存在,1 <= i <= n。
删除操作后的结果:
在线性表L中删除序号为 i 的数据元素,删除后使得序号为:i+1 , i+2 , ··· , n , 的数据元素的序号变为:i , i+1 , ··· , n - 1,新表长 = 原表长 - 1。
线性表的物理结构
(一)顺序存储结构以及其基本运算
特点:在内存中用一块连续的存储空间顺序存放线性表的各种元素,也称为顺序表。由于内存中的地址空间是连续的,所以用物理上的相邻实现数据元素之间逻辑相邻关系是简单的,只要知道顺序表首地址和每个数据元素所占地址单元的个数,就能得到第 i 个数据元素的地址来,这是顺序表具有的按数据元素序号随机存取的特点。
总的来说:线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
我们在实现顺序表的基本操作时,可以通过完成某些功能来掌握顺序表的基本操作并实现算法,在这里我们通过制作一个简单的“职工信息管理系统”来实现相关算法。
项目需求:
- “职工信息管理系统”中每个职工记录包含职工编号no 、姓名name、部门号depno、和工资数salary信息;
- 能够插入一个职工记录。
- 能够显示所有职工记录。
- 按编号no对所有职工记录进行递增排序。
- 按部门号depno对所有职工记录进行递增排序。
- 按工资数salary对所有职工记录进行递增排序 。
- 能够删除要删除的职工记录。
线性表有插入、删除、等运算,即表长是可变的,因此数组的容量需要设计的足够大。
假设用data[MaxSize]来表示,那么MaxSize就要根据你的实际情况来设置,比如在下面代码中定义MaxSize为50,即线性表能够存储50个连续的数据元素。
数据元素的存放空间在data[0] 到 data[MaxSize-1] ,但是线性表的可用空间长度为MaxSize=50。
项目代码:
#include "stdio.h"
#define MaxSize 50
struct Employee{ //在这里定义一个结构体Employee
int no;
int depno;
char name[10]; //定义char类型数组长度为10来存储员工姓名
float salary;
};
typedef Employee DataType; //将结构体Employee定义为别名DataType,实质上是相等的
typedef struct Seq { //在定义顺序表的同时将顺序表设置为别名LNode。
DataType data[MaxSize]; //即Employee data[MaxSize];
int length;
}LNode;
//线性表的初始化
void Init_List(LNode *L) { //LNode *L 为形参
L->length = 0; //将表中length指针设置为0,表示表中没有元素。
}
//创建线性表来存储员工信息
void Create_List(LNode* L) {
int i = 0, no; //员工编号
Init_List(L); //先初始化表
while (printf("请输入员工编号,以负数结尾\n"), scanf("%d", &no), no > 0)
{ //用户输入的编号小于0停止
L->data[i].no = no; //将用户输入的编号no放到表中的data[i]中,第一个元素i=0
printf("请输入员工姓名、部门编号、员工薪水,用空格隔开。\n");
scanf("%s%d%f", L->data[i].name, &L->data[i].depno, &L->data[i].salary);
i++; //当用户输入第一个元素后i++表示接着存入第二个元素
}
L->length = i; //长度赋值 //停止输入后i即为表长,赋值给表中的length
}
//输出员工相关信息
void display(LNode* L) {
int i;
for (i = 0; i < L->length; i++){
printf("%d %s %d %.2f\n", L->data[i].no, L->data[i].name, L->data[i].depno, L->data[i].salary);}
printf(" \n");
}
//按照员工薪水对员工信息进行排序(升序)
void sort_salary(LNode *L){
int i,k,n;Employee t; //定义一个中间值t来进行交换
n=L->length; //表长赋值为 n
for (i = 1; i < n; i++){ //外循环的次数小于表长 n
for ( k = 0; k < n - i; k++) {
if (L->data[k].salary > L->data[k+1].salary){ //当表中前面一个薪水大于后面一个时交换
t = L->data[k];
L->data[k]= L->data[k+1];
L->data[k+1]=t;
}
}
}
printf("按照薪水的排序如下:\n");
}
//按照员工的部门编号排序(升序)
void sort_depno(LNode *L){
int i,k,n;Employee t;
n=L->length;
for (i = 1; i < n; i++){
for ( k = 0; k < n - i; k++) {
if (L->data[k].depno > L->data[k+1].depno){
t = L->data[k];
L->data[k]= L->data[k+1];
L->data[k+1]=t;
}
}
} printf("按照部门编号的排序如下:\n");
}
//按员工编号排序(升序)
void sort_no(LNode *L){
int i,k,n;Employee t;
n=L->length;
for (i = 1; i < n; i++){
for ( k = 0; k < n - i; k++) {
if (L->data[k].no > L->data[k+1].no){
t = L->data[k];
L->data[k]= L->data[k+1];
L->data[k+1]=t;
}
}
}
printf("按照员工编号的排序如下:\n");
}
//插入员工信息
void inputEmp(LNode *L,int i,Employee t){
int k;
if(i<1|| i>L->length+1){//插入的位置小于表长或超过表长+1(前面会有一个空值)时就不能插入
printf("插入位置不合理\n");}
for(k=L->length-1; k>=i-1;k--) //当插入的位置合理时,将该位置(i)及其后面元素后移
L->data[k+1] = L->data[k]; //L->data[k]为最后一个元素,将其向后移L->data[k+1]
L->data[i-1]=t; //全部后移后将t中的元素放入已置空的L->data[i-1]中
L->length++; //插入一个元素后表长+1
}
//根据职工编号删除员工信息
void deleteEmp(LNode *L,int eno){
int i,k;
for(i=0;i<L->length;i++){
if(L->data[i].no==eno) break; //循环查找表中员工编号为 eno的员工信息,
}
if(i<L->length){
for(k=i;k<L->length-1;k++)
L->data[k]=L->data[k+1];
}
L->length--;
}
void main(){
LNode List;
int i;
Employee t;
Create_List(&List);
sort_salary(&List);
display(&List);
sort_depno(&List);
display(&List);
sort_no(&List);
display(&List);
printf("插入员工信息(编号,姓名,部门编号,薪水)\n");
printf("请先输入要插入的位置: \n");
scanf("%d",&i);
printf("请再输入员工编号、姓名、部门编号、薪水\n");
scanf("%d%s%d%f",&t.no,t.name,&t.depno,&t.salary);
inputEmp(&List,i,t);
display(&List);
printf("请输入要删除的职工编号\n");
scanf("%d",&i);
deleteEmp(&List,i);
printf("职工编号为%d的员工信息已被删除!\n",i);
display(&List);
}