数据结构3_线性表_顺序表的基本操作及实现

数据结构3_线性表_1

总览:

在这里插入图片描述

线性表:

线性表是具有相同数据类型的n(n>=0)个数据元素的有序序列,其中n为表长,当n=0时线性表是一个空表。若用L命名线性表,其一般表示为:
L = ( a 1 , a 2 , a 3 , a 4 , ∗ ∗ ∗ , a n ) L = (a1,a2,a3,a4,***,an) L=(a1,a2,a3,a4,,an)
a1为表头元素,an为表尾元素,除了an其他元素都有唯一的直接后继,除了a1其他元素都有唯一前驱。

线性表的特性:

  1. 表中元素个数有限;
  2. 表中元素具有逻辑上的顺序性,表中元素有先后次序;
  3. 表中元素都是数据元素,每个元素都是单个元素;
  4. 表中元素的数据类型都相同,意味着每个元素占有相同大小的存储空间;

1 顺序存储——顺序表:

顺序表采用顺序存储方式,即逻辑上相邻的数据在计算机内的存储位置也是相邻的,即顺序表表中元素的逻辑顺序与其物理顺序相同;
在这里插入图片描述

顺序表可以分为静态分配和动态分配两种:

静态分配:

#define MaxSize 50  //顺序表的最大长度
typedef struct{		//typedef类型重命名
    ElemType data[MaxSize]; //顺序表的元素,ElemType是未明确的数据类型,使用时可以用typedef定义具体类型
    int length;				//长度
}SqList;

静态分配方法需要预先分配一段固定大小的连续空间,但在运算过程中,进行插入,合并等操作时,容易超过预分配的空间长度,出现溢出问题,所以可以采用动态分配:

动态分配:

#define InitSize 50  //顺序表的初始长度
typedef struct{		//typedef类型重命名
    ElemType *data; //指向动态分配数组的指针,基地址,*取内容
    int MaxSize,length;	//数组的最大容量和当前个数
}SeqList;

/**
	初始动态分配语句
*/
L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);//c语言
L.data = new ElemType[InitSize];//c++ new在堆上开辟一段新的内存空间返回首地址

堆栈:简单来说,栈区放形参和局部变量,编译器自动分配和释放,速度快;堆区放其他变量,程序员分配和释放,速度慢,容易产生碎片;

1.1 顺序表的基本操作:
1.1.1 初始化和创建操作:
struct SqList{
	int data[MaxSize]; //存放顺序表的元素
	int length; //存放顺序表的长度
	int last;
};

void Init(SqList *L){//void Init(SqList &L)
	L->data[0] = int(malloc(MaxSize * sizeof(int)));//初始化
	int n, i = 0;
	printf("请输入元素顺序表个数:");//接下来是创建,初始化和创建有的书也分为两个函数去写
	cin >> n;
	L->length = n;
	while (i < n)
	{
		cin >>(L->data[i++]);
	}
	L->last = i - 1;
}

指针传递:void Init(SqList *L)(直接寻址,直接操作实参地址)

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作,当然也会在栈中开辟一块空间存放实参的副本;

引用传递:bool InsertList(SqList &L, int i, int e)(间接寻址,先在栈中找地址,再去地址修改)

形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

两种传参方式都可以直接修改实参的值(搞不懂跳过,记住这两种都可以改变实参的值就ok)

1.1.2 插入操作:
/*顺序表的插入操作*/
bool InsertList(SqList &L, int i, int e)
{
	//在顺序表中第i个位置(位序,不是下标)插入数值e
	int j;
	if (i<1 || i>L.length+1) //判断是否越界
		return false;
	if (L.length == MaxSize)//内存已满
		return false;
	L.length++;            //长度++
	for (j = L.length; j >= i; j--) //将第i个起的数据后移
		L.data[j] = L.data[j - 1];
	L.data[j] = e;
	return true;
}

. -> :: 的区别

如果有个变量MyStruct s,那么使用其中的成员元素时可以用
s.member_a = 1;

如果采用指针方法访问,比如MyStruct * ps,那么同样的访问必须用箭头号:

ps->member_a = 1;

:: 只用在类成员函数和类成员变量中。

算法复杂度: 最好O(1),最坏O(n),平均O(n)

1.1.3 删除操作:
/*顺序表的删除*/
bool DeleteList(SqList&L, int i)
{
	//删除顺序表中第i个元素
	int j;
	if (i<1 || i>L.length)
		return false;   //判断越界
	for (j = i; j < L.length; j++)
		L.data[j - 1] = L.data[j];
	L.length--;
	return true;
}

算法复杂度: 最好O(1),最坏O(n),平均O(n)
在这里插入图片描述

1.1.4 按值查找:
/*顺序表的查找*/
bool LocateElem(SqList L, int e)
{
	int i;
    for(i = 0; i < L.length; i++){
        if(L.data[i] == e){
            return i+1;
        }
    }
    return 0; //查找失败
}

算法复杂度: 最好O(1),最坏O(n),平均O(n)

1.1.5 合并:
/*顺序表的合并*/
void MergeList(SqList *LA, SqList *LB, SqList *LC)
{
	int i = 0, j = 0, k = 0;
	while ((i <= LA->last) && (j <= LB->last))
	{
		if (LA->data[i] <= LB->data[j])
		{
			LC->data[k] = LA->data[i];
			i++;
			k++;
		}
		else
		{
			LC->data[k] = LB->data[j];
			j++;
			k++;
		}
	}
	while (i <= LA->last)
		//当表LA有剩余元素时,则将表LA的剩余元素赋给表LC	
	{
		LC->data[k] = LA->data[i];
		i++;
		k++;
	}
	while (j <= LB->last)
		//当表LB有剩余元素时,则将表LB的剩余元素赋给表LC	
	{
		LC->data[k] = LB->data[j];
		j++;
		k++;
	}
	LC->last = LA->last + LB->last + 1;

}

1.1.6 输出:
/*顺序表的输出*/
void OutPutList(SqList&L)
{
	for (int i = 0; i < L.length; i++)
		printf("%d ", L.data[i]);
	printf("\n");
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值