您的位置:首页 > 理论基础 > 数据结构算法

数据结构之线性表

2013-11-27 10:55 330 查看
1:线性表:谈到线性表,可以联想到26个英语字母,他们从逻辑上组成一个有序的序列就是线性表,另外,线性表也可以是班上的成绩登记表,其中包括学号,姓名,还有各科的成绩等等。对于一个非空的线性表,注意:各个元素的长度是相同的:

2:线性表的基本运算包括 a:初始化 b计算表长 c获取结点 d查找结点e插入结点 f删除结点

在这里,我们讨论了线性表的逻辑结构和数据运算,还没有对其存储结构进行讨论,在计算机中,线性表采用二种方法来存储,一种是顺序存储,另一种是链式存储,顺序存储的线性表叫顺序表,链式存储的表叫链表

A:顺序结构表

因为顺序结构表在存储方式上是连续的,因此,只要知道该顺序表的首地址,以及每个元素占用的存储长度,就可以计算出任何一个数据元素的位置(也就是可以计算出任何衣蛾结点的位置),这种思想是我们操作顺序表结构的基本思想Loc(Ai) = Loc(a1)+(i-1)*c;

操作顺序表的步骤

1:准备数据:也就是准备顺序表中需要用到的变量以及数据结构等等

示例代码:

#define MAXLEN 100 //定义顺序表的最大长度

typedef struct
{
char key[10];//定义节点关键字
char name[20];
int age;
}DATA;//定义结点类型

typedef struct
{
DATA ListData[MAXLEN+1];//保存顺序表的结构数组
int ListLen;//顺序表已保存的节点数

}SLType;


其实这里我们定义了一个顺序表,这里可以记录100个学生的基本情况,其中顺序表的数据元素类型是DATA,以及顺序表的数据结构SLType。在数据结构SLType中,ListLen为顺序表已存在的结点数量,也就是当前顺序表的长度,ListData是一个数组,用来存放各结点数据

2:初始化一个顺序表

在使用顺序表之前,我们要创建一个空的顺序表,也就是初始化顺序表,这里程序中只需要设置顺序表的结点数量ListLen等于0即可。在后面添加的元素将从顺序表的第一个位置存储

void SLInit(SLType *SL)
{
SL->ListLen =0;//初始化顺序表

}


需要注意的是,我们这里没有清空顺序表,如果原来顺序表中有数据,也会被覆盖,但是不会影响chaozuo

3:计算顺序表的长度

示例代码:

int SLLength(SLType *SL)
{
return(SL->ListLen);//返回顺序表的结构

}


计算顺序表的结构也就是

插入结点:在线性表L中插入一个新的结点,使得结点后面的编号依次加一,这是,插入新的结点后,线性表的长度将变为N+1,插入结点的难点在于随后的每个数据都要进行移动计算量比较大

int SLInsert(SLType*SL,int n,DATA data)
{
int i;
if(SL ->ListLen >= MAXLEN)//顺序表的结点数量已经超过最大数量
{
printf("顺序表已满,不能插入结点");
return 0;

}

if(n<1 ||n>SL->ListLen-1)//插入的结点不正确
{
printf("插入元素序号错误,不能插入元素");
return 0;
}

for(i = SL->ListLen;i>=n;i--)//将表中的数据向后移动一位
{
SL->ListData[i+1] = SL->ListData[i];

}
SL->ListData
= data;//插入结点
SL ->ListLen++;//顺序表的结点数量增加1

return 1;//插入成功表示返回1

}


这里程序要先判断顺序表的结点数量是否超过最大的数量,以及插入结点的序号是否正确,但条件满足的时候,便将顺序表中的数据向后移动,同时插入结点,并更新ListLen

追加结点:

int SLAdd(SLType*SL,DATA data)
{
if(SL->Listen>=MAXLEN)
{
printf("顺序表已满,不能在添加结点");
return 0;
}
SL->ListData[++SL->ListLen] = data;
return 1;

}


追加结点并不是基本的数据结构操作,但是由于算法比较简单,这里单独给出代码

删除结点:

int SLDelete(SLType*SL,int n)
{
int i;
if(n<1||n>SL->ListLen+1)
{
printf("删除结点序号错误,不能删除结点");
return 0;
}
for(i = n;i<ListLen;i++)//将顺序表中的数据向前移动即可
{
SL->ListData[i] = SL->ListData[i+1];
}
SL->ListLen --;
return 1;//成功的话,返回值为1
}


这里首先判断待删除的及结点序号是否正确,如果正确,开始移动数据,并更新结点数量ListLen

查找结点

查找结点,顾名思义就是查找值为x的结点,并返回该结点在线性表中的位置,如果在线性表中没有找到结点为x的结点则返回一个错误标志,根据x类型的不同,查找的方式可以分为按序号查找结点或按关键字查找结点

按照序号查找结点:

DATA*SLFindByNum(SLType*SL,int n)
{
if(n<1||n>SL->ListLen+1)
{
printf("结点序号错误");
return NULL;
}

return &(SL->ListData
);
}


对于一个顺序表,序号就是数据元素在数组中的位置,也就是数组元素的下标标号,按照序号查找结点是顺序表查找的最常用的方法,这是因为顺序表存储本身就是一个数组

按照关键字查找结点:

int SLFindByCont(SLType*sl,char *key)
{
int i;
for(i= 1;i<SL->ListLen;i++)
{
if(strcmp(sl->Data[i].key,key)==0)
return i;
}

return 0;
}


这是一个比较常见的按照关键字进行查找的例子,我们可以看作是学生的学号为关键字

显示所有结点:

int SLAll(STLType*SL)
{
int i;
for(i=1;i<SL->ListLen;i++)
{
printf("(%s,%S,%D)\N",Sl->ListData[i].key,SL->ListData[i].name,SL->ListData[i].age);
return 0;
}
}


显示所有结点的数据并不是数据结构的基本运算,因为他可以是简单的逐个引用结点来实现,这里单独列出一个函数,用来操作显示所有结点

冒泡法排序:

#include<stdio.h>
#include<string.h>

#define MAXLEN 100
typedef struct
{    char key[10];
char name[20];
int age;
}DATA;

typedef struct
{
DATA ListData[MAXLEN];
int ListLen;
}SLType;
//初始化顺序表
void SLInit(SLType *SL)
{
SL->ListLen = 0;
}
//计算顺序表的长度
int SLLength(SLType *SL)
{
return (SL->ListLen);
}

//插入结点
int SLInsert(SLType*SL,int n,DATA data)
{
int i;
if(SL->ListLen >=MAXLEN)
{
printf("结点已经满了");
return 0;
}
if(n<0||n>MAXLEN)
{
printf("插入的结点有误");
return 0;
}
for(i = SL->ListLen;i>n;i--)
{
SL->ListData[i+1] = SL->ListData[i];
}
SL->ListData
= data;
SL->ListLen ++;    return 1;
}

//增加结点
int SLAdd(SLType *SL,DATA data)
{
if(SL->ListLen >MAXLEN)
{
printf("增加失败,结点已经满了");
return 0;
}
SL->ListLen ++;
SL->ListData[SL->ListLen] = data;
return 1;
}

//删除结点
int SLDelete(SLType*SL,int n)
{
int i;
if(n<0||n>SL->ListLen+1)
{
printf("删除结点失败");
return 0;
}
for(i = n;i<SL->ListLen;i++)
{
SL->ListData[i] = SL->ListData[i+1];
}
SL->ListLen--;
return 1
;}
//按序号查找
DATA *SLFindByNum(SLType*SL,int n)
{
if(n<0||n>SL->ListLen)
{
printf("查找结点失败");
return NULL;
}
return &(SL->ListData
);}

//按关键字查找
int SLFindByCont(SLType*SL,char *key)
{
int i;
for(i=0;i<SL->ListLen;i++)
{
if(strcmp(SL->ListData[i].key,key)==0)
return i;
}
return 0;
}

//显示所有结点
int SLAll(SLType*SL)
{
int i;
for(i = 0;i<SL->ListLen;i++)
{
printf("%s,%s,%d",SL->ListData[i].key,SL->ListData[i].name,SL->ListData[i].age);
}
return 0;
}
int main()
{
int i;
SLType SL;
DATA data;
DATA *pdata;
char key[10];
printf("顺序表演示\n");
SLInit(&SL);//初始化顺序表
printf("顺序表初始化完成\n");

do
{
printf("输入添加的结点(学号,姓名,年龄)");
fflush(stdin);//清空输入缓存区
scanf("%s%s%d",&data.key,&data.name,&data.age);
if(data.age)
{
if(!SLAdd(&SL,data))//添加结点失败
{
break;
}
}
else//年龄为0,退出死循环
{
break;
}
}while(1);
printf("\n顺序表中的结点顺序\n");
SLAll(&SL);//显示所有结点数据
fflush(stdin);
printf("\n需要取出的结点\n");
scanf("%d",&i);
pdata = SLFindByNum(&SL,i);
if(pdata)
{
printf("第%d个结点为:(%s,%s,%d)",i,pdata->key,pdata->name,pdata->age);
}
fflush(stdin);
printf("\n要查找的结点的关键字\n");
scanf("%s",key);
i = SLFindByCont(&SL,key);
pdata = SLFindByNum(&SL,i);
if(pdata)
{
printf("第%d个结点为:(%s,%s,%d)\n",i,pdata->key,pdata->name,pdata->age);
//    getch();
return 0;
}
return 0;
}


View Code

版权所有,转载请注明链接地址:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: