数据结构第二章C语言———线性表

数据结构第二章C语言 —— 线性表

1.什么是线性表

线性表是一种线性结构。线性结构是除了第一个元素无直接前驱,最后一个无直
接后继外,其他每个数据元素都有一个前驱和后继的数据结构。

(线性表,栈,队列,串和数组都属于线性结构。)
在这里插入图片描述

2案例引入

比如多项式的运算,建立图书管理系统并进行各种操作。都可用到线性表。

3线性表的类型定义

线性表一种最常用且最简单的数据结构

线性表是一个相当灵活的数据结构,它的长度可根据需要增长或缩短,即对线性表的数据元素

不仅可以进行访问还可以进行插入删除等操作。

抽象数据类型线性表的定义如下:
在这里插入图片描述

4.1线性表的顺序表示和实现

线性表是用一组地址连续的存储单元,依次存储线性表中的数据元素,从而使得

逻辑上相邻的两个元素在物理位置上也相邻。第 1 个元素存储在线性表的起始位

置,第 i 个元素元素的存储位置后面紧接着存储的是第 i + 1 个元素。因此,顺序

表的特点是表中元素的逻辑顺序与其物理顺序相同。

一般来说,线性表的第i个数据元素ai的存储位置为:

					LOC(ai) = LOC(a1) +  (i-1)*l;

在这里插入图片描述

#define MAXSIZE 100   //顺序表的最大长度
struct Sqlist{		//定义的结构体,名字叫做Sqlist
	int length;		//当前长度
	Elemtype *elem;//存储空间的基地址
}

注意:

  1. 初始化完成后,数组指针elem指示顺序表的基地址;数组空间大小为MAXSIZE

    2. 什么是Elemtype,我在这引用这位大神的

在定义结构体array的时候有这样一段:
typedef struct
{
ElemType data[maxsize];
int length;
}array;
在《数据结构》中,关于数据元素的类型定义均用“ ElemType e;”来表示,其中e是表示数据元素的变量,而ElemType则是它的类型,ElemType的含义就是“数据元素的类型”,是一个抽象的概念,是表示我们所要使用的数据元素应有的类型。
使用:typedef int ElemType;//定义ElemType为int类型
你想让它是什么类型自己用typedef重定义就行。
也可以用模板表示,类似template里面的T。
这对于初学数据结构的学生来说理解起来有些难度,为了利于理解,我们可以把”ElemType“等同于”一套房子“来理解:
“一套房子”的含义大家都非常清楚,但一套房子的具体含义是因人而异的,有的认为是“四室二厅”,有的认为是“二室一厅”,也有的认为是“一室一厅”,对此大家也没有任何异议!其实ElemType也是这样的,它有时表示“整型”,有时表示“用户自定义的结构体”,也可以是其他形式的类型自由表示!

3.length表示顺序表中当前数据元素的个数。C语言数组下标是从0开始的,而位置序号是1开始的。所以数据元素a1,a2,a3…an 存放在elem[0],elem[1],elem
[2]…elem[n-1]中 。

示例:
用线性表存储图书馆的数据

#define MAXSIZE 100
struct Book{//定义一个名字为Book的结构体
	char no[20];//书的序列号
	int price;//价格
	char name[20];//名字
}

struct SqList{//图书表的顺序存储结构类型为Sqlist
	Book *elem;//储存位置的基地址
	int length;//当前长度
}

Sqlist L;//上述定义完后,可定义“Sqlist L”;把L,定义为Sqlist.便可以使用L.elem[i-1]访问表中位置序号为i的图书记录

4.2顺序表中基本操作的实现

4.2.1 判断是否为空

int ListEmpty(SqList L)
{
    if (L.length == 0)
        return OK;//关于OK的定义会在最后的汇总中讲
    else
        return ERROR;//关于ERROR的定义会在最后的汇总中讲
}

4.2.2 返回长度

int length(Sqlist L)
{
	return  L.length;
}

上述两个方法都比较容易实现因为表的长度是顺序表的一个属性,直接返回 L 的length 值即可。

4.2.3顺序表的初始化

这里我开始也分不清楚 顺序表初始化 和 顺序表的顺序表示 两则和的区别。

后来自己想觉得两者的区别就像是

顺序表的顺序表示 为 我定义a为int型;
顺序表初始化 为 a = 100;(不过这里要特殊点,顺序表的初始化要求都为0)

初始化的步骤:

1 >使顺序表L动态分配一个预定义大小为MAXSIZE的数组空间elem(数组元素的基地址)指向这段空间的基地址
2> 将表的当前长度设为0。

int InitList (SqList *L)//我要对线性表L进行修改,所以要用到*,用指针作为参数
{
	L.elem = MAXSIZE;//将顺序表的大小定为MAXSIZE
	if(!L.elem)//如果L的储存数据元素的基地址为0,就退出失败;
		exit (ERROR);
	L.length = 0;//L当前的长度为0;
	retrun OK;
}

关于exit和return的区别

4.2.4顺序表的取值

由于我们前面提到过:*“length表示顺序表中当前数据元素的个数。C语言数组下标是从0开始的,而位置序号是1开始的。所以数据元素a1,a2,a3…an 存放在elem[0],elem[1],elem[2]…elem[n-1]中 。”*所以在取第i个数据元素时我们对elem[i-1]进行操作

算法步骤:
1>判断位置合不合理
2>取值

int GetELem(Sqlist L,int i,Elemtype *e)
{
	if(i < 1 || i>L.length)
		return ERROR;
	else 
		 *e = L.elem[i-1];
		return OK;
}

4.2.5顺序表的查找

给出数据e找到数据e相等的元素L.elem[i]。
算法步骤
1>从第一个数据开始进行查找,如果找到了返回与e相等的L.elem[i],返回i+1;
2>如果没有找到,返回ERROR

	int LOcateElem(SqList L,ElemType e)
	{
		for(int i  =  0 ; i < L.length ; i++)
			if(elem[i]  = e)
				return i+1;
			else return  ERROR;
	}

4.2.6顺序表的插入

因为线性表的物理顺序与实际的存储顺序一致,所以我在第i上插入一个元素,i后面的元素都要向后移动(实际上顺序表并不适合大规模的实现插入和删除

算法实现步骤:
1>判断给出的位置i是否合理
2>判断存储空间是否满,(满了无法插入
3>将第i个位置上的元素到第n个元素都向后移动一个位置,若要移动的是最后一个即第i+1个,则无需向后移动
4>将要插入的元素e插入到第i个位置
5>L的length加1

int LIstInsert(SqList &L,int  i ,ElemType e)
{
	if(i<1||i>L.length) return ERROR;//判断给出的位置i是否合理
	if(L.length + 1 > MAXSIZE)	return ERROR;//判断存储空间是否满,(*满了无法插入*)
	for(int j = L.length-1 ; i>=i-1 ; i++)//将第i个位置上的元素到第n个元素都向后移动一个位置,若要移动的是最后一个即第i+1个,则无需向后移动
		L.elem[j+1] = L.elem[j];
	L.elem[i-1] =  e;//将要插入的元素e插入到第i个位置
	L.length++;//L的length加1
	return OK:	
}

4.2.7顺序表的删除

和线性表的插入差不多,插入是i到n的元素向后移动,删除是i到n向前移动
算法步骤:
1>判断i的位置是否合理;
2>将第i+1个到第n个的元素 向前移动
3>length-1;

int ListDelete (Sqlist &L,int i)
{
	if(i<1||i>L.length)return ERROR;//判断i的位置是否合理;
	for(int j = 1;j<=L.length;j++)//将第i+1个到第n个的元素 向前移动
		L.elem[j-1]  = L.elem[j];
		L.length--;
		return OK;
}

4.2.7顺序表的全部输出

这没啥好讲的,直接看代码

int ListTravse(Sqlist L)
{
	fot(int i = 0;i<L.length;i++)
	cout<<L.elem.[i]<<" "<<endl;	//C++的输出流方式
	return OK;
}

线性表的全部实现

#include<stdio.h>
#include<stdlib.h>

#define OK       1					//我要先定义了OK是啥,后面才能用
#define ERROR    0					//一样的
#define MAXSIZE  20

typedef struct {
    int data[MAXSIZE];                //数组,存储线性表数据
    int length;                		  //线性表长度
}SqList;

/*初始化线性表*/
int InitList(SqList *L)
{
    L->length = 0;
    return OK;
}

/*判断线性表是否为空,为空返回OK,否则返回ERROR*/
int ListEmpty(SqList L)
{
    if (L.length == 0)
        return OK;
    else
        return ERROR;
}

/*清除线性表*/
int ClearList(SqList *L)
{
    L->length = 0;
    return OK;
}

/*返回线性表长度*/
int ListLength(SqList L)
{
    return L.length;
}

/*返回L中第i个数据元素的值*/
int GetElemt(SqList L, int i, int *e)
{
    if (L.length == 0 || i < 0 || i > L.length)
        return ERROR;
    else
        *e = L.data[i - 1];

    return OK;
}

/*返回线性表中第1个与e满足关系的位置*/
int LocateElem(SqList L, int e)
{
    int i;
    if (L.length == 0)
        return ERROR;

    for (i = 0; i < L.length; i++)
    {
        if (L.data[i] == e)
            break;
    }

    if (i >= L.length)
        return ERROR;

    return i + 1;

}

/*在线性表L的第i个位置插入新的数据元素e*/
int ListInsert(SqList *L, int i, int e)
{
    int k;
    if (L->length == MAXSIZE)
        return ERROR;
    if (i<1 || i>L->length + 1)
        return ERROR;

    if (i <= L->length)
    {
        for (k = L->length ; k >= i; k--)
        {
            L->data[k] = L->data[k-1];
        }
    }

    L->data[i-1] = e;
    L->length++;

    return OK;

}

/*删除线性表L的第i个元素*/
int ListDelet(SqList *L, int i, int *e)
{
    int k;
    if (L->length == 0)
        return ERROR;
    if (i < 1 || i > L->length)
        return ERROR;

    *e = L->data[i - 1];
    if (i < L->length)
    {
        for (k = i; k < L->length; k++)
            L->data[k-1] = L->data[k];
    }
    L->length--;
    return OK;

}

/*依次输出线性表L中的元素*/
int ListTravse(SqList L)
{
    int i;
    for (i = 1; i <=L.length; i++)
        printf("%d", L.data[i-1]);
    printf("\n");

    return OK;
}

void unionL(SqList *La, SqList Lb)
{
    int La_len, Lb_len,i;
    int e;
    La_len = ListLength(*La);
    Lb_len = ListLength(Lb);
    for (i = 1; i <= Lb_len; i++)
    {
        GetElemt(Lb, i, &e);
        if (!LocateElem(*La, e))
            ListInsert(La, ++La_len, e);
    }
}

int main()
{
    SqList L;
    SqList Lb;
    int e;
    int i;
    int j, k;
    i = InitList(&L);
    printf("初始化线性表L后长度为:%d\n", L.length);
    for (i = 1; i <= 5; i++)
        j = ListInsert(&L, 1, i);
    ListTravse(L);
    printf("线性表L后长度为:%d\n", L.length);
    i = ListEmpty(L);
    printf("L是否为空:i=%d(0为非空,1为空\n", i);
    i = ClearList(&L);
    printf("L是否为空:i=%d(0为非空,1为空\n", i);

    for (j = 1; j <= 10; j++)
    {
        i = ListInsert(&L, j, j);
    }
    printf("在L末尾依次插入1到10后,L.data=\n");
    ListTravse(L);
    printf("L.length = %d\n", L.length);
    ListInsert(&L, 1, 0);
    printf("在L表头插入0后L.data为\n");
    ListTravse(L);
    GetElemt(L, 5, &e);
    printf("第5个数据为%d\n",e);
    for (j = 3; j <= 4; j++)
    {
        k = LocateElem(L, j);
        if (k)
            printf("第%d个元素为%d\n", k, j);
        else
            printf("线性表中没有%d这个元素\n", j);
    }

    j = 5;
    k = ListDelet(&L, j, &e);
    if (k = ERROR)
        printf("删除第j个元素失败");
    else
    printf("删除的第%d个元素为%d\n",j, e);

    printf("依次输出L的元素\n");
    ListTravse(L);
    i = InitList(&Lb);
    for (j = 6; j <= 15; j++)
        i = ListInsert(&Lb, 1, j);
    ListTravse(Lb);
    unionL(&L, Lb);
    printf("合并了Lb的L元素\n");
    ListTravse(L);
    return 0;

}

后记:
1-数据结构中" . "和“->”的区别
2-指针中*和&的区别
3-这是我期末复习的总结,有错误的地方请大家海涵

参考资料:
1.winner_chenwei关于线性表的文章
2.数据结构C语言版第二版严蔚敏版 中国工信出版集团 第二章 线性表

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值