数据结构之线性表

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[n] = 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[n]);
}

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

 

按照关键字查找结点:

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>
#define Len 10

//冒泡法的基本算法
void BubbleSort(int *a)
{
    int i,j,temp;
    for(i = 0;i<Len-1;i++)
        for(j = Len-1;j>i;j--)//从后面开始往前面比较这样比较容易理解
        {
            if(a[j-1]>a[j])
            {
                temp = a[j-1];
                a[j-1] = a[j];
                a[j] = temp;
            }
        }
}
int main()
{
    int a[Len],i;
    printf("please input a[10]\n");
    for(i = 0;i<Len;i++)
        scanf("%d",&a[i]);
    
    BubbleSort(a);

    printf("the order is:\n");
    
    for(i = 0;i< Len;i++)
        printf("%3d",a[i]);
    printf("\n");
    
    return 0;
}
View Code

 

顺序表操作

#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[n] = 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[n]);}

//按关键字查找
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

 

版权所有,转载请注明链接地址:

posted @ 2013-11-27 10:55  跨七海的风  阅读(293)  评论(0编辑  收藏  举报