408考研-数据结构-线性表

文章目录

    • 考点一:基本定义和结构
    • 考点二:线性表的顺序存储
      • 基础代码
        • 1.1创建顺序表
        • 1.2 初始化/销毁顺序表
        • 1.3 判断表是否为空
        • 1.4 获取表的长度
        • 1.5 输出/打印表
        • 1.6 返回某个位置的数据的元素值,某个值的位置
        • 1.7 插入
        • 1.8 删除
      • 进阶应用
        • 2.1 删除
        • 2.2合并表
        • 2.3 逆置
        • 2.4 基准分割
        • 2.5 类型划分
  • 题目:
  • 其他:

》》 沐沐雪:“代码还是要自己手敲,逻辑思路最好在纸上笔划以下,才能理解的更清晰深刻”

考点一:基本定义和结构

线性表:

  1. 具有相同类型的数据元素的有限序列,具有一对一的逻辑关系,相邻元素有前驱和后继的关系
  2. 元素的下标代表元素在线性表中的位置
  3. 除第一个元素,其他的都有前驱,除最后一个元素,其他的都有后继
  4. 空间连续,提前分配;查找容易,增删难
  5. 逻辑关系是由存储位置表示的

考点二:线性表的顺序存储

顺序表:线性表的节点按照逻辑顺序依次存放到连续的存储单元里面的表
ps:这里的连续指的是内存单元地址的连续

所以元素的存储位置LOC(ai)满足以下关系
L C O ( a i ) = L O C ( a i ) + L LCO(a_i) = LOC(a_i) + L LCO(ai)=LOC(ai)+L

基础代码

//顺序表基本运算算法
#include <stdio.h>
#include <malloc.h>
#define MaxSize 50
typedef int ElemType;
typedef struct
{
	ElemType data[MaxSize];		//存放顺序表元素
	int length;					//存放顺序表的长度
} SqList;						//顺序表的类型
1.1创建顺序表
void CreateList(SqList*& L, ElemType a[], int n)
{
	L = (SqList*)malloc(sizeof(SqList));
	for (int i = 0; i < n; i++)
		L->data[i] = a[i];
	L->length = n;
}

注:

  • 这里使用到的malloch函数需要导包:#include <malloc.h>

  • SqList* L 和SqList* &L 的区别

    &是引用符号
    在函数调用的时候,我们传入的都是真实的数据,称之为实参,而函数内代码使用到的叫做形参
    在数据传入的时候,会按照你传入的数据copy一份来进行运算,真实的数据并不会加入运算。
    但是引用不是,它的参数是直接使用真实的数据的。

1.2 初始化/销毁顺序表
void InitList(SqList*& L)
{
	L = (SqList*)malloc(sizeof(SqList));	//分配存放线性表的空间
	L->length = 0;
}
void DestroyList(SqList*& L)
{
	free(L);
}
1.3 判断表是否为空
bool ListEmpty(SqList* L)
{
	return(L->length == 0);
}
1.4 获取表的长度
int ListLength(SqList* L)
{
	return(L->length);
}
1.5 输出/打印表
void DispList(SqList* L)
{
	for (int i = 0; i < L->length; i++)
		printf("%d ", L->data[i]);
	printf("\n");
}
1.6 返回某个位置的数据的元素值,某个值的位置
bool GetElem(SqList* L, int i, ElemType& e)
{
	if (i<1 || i>L->length)
		return false;
	e = L->data[i - 1];
	return true;
}
int LocateElem(SqList* L, ElemType e)
{
	int i = 0;
	while (i < L->length&& L->data[i] != e) i++;
	if (i >= L->length)
		return 0;
	else
		return i + 1;
}

需要特别注意:如果你想要返回的是第一个元素,对应的是a[0],而不是a[1]。返回的值,会传给e这个变量

1.7 插入
bool ListInsert(SqList*& L, int i, ElemType e)
{
	int j;
	if (i<1 || i>L->length + 1 || L->length == MaxSize)
		return false;
	i--;						//转化为elem数组的下标
	for (j = L->length; j > i; j--) 	//将data[i]及后面元素后移一个位置
		L->data[j] = L->data[j - 1];
	L->data[i] = e;
	L->length++;				//顺序表长度增1
	return true;
}

注意:

  • 比如说你要插入到第一位,那么原来在第一个位置上的元素,和一后面的元素都得向后移动一位
  • 长度也就是顺序表的内元素的个数length要 “+1”
  • 插入的条件,你不能在表满的时候插入进去,也不能插入在负数的位置
  • 时间复杂度:最好情况O(1),最坏情况O(n)
1.8 删除
bool ListDelete(SqList*& L, int i, ElemType& e)
{
	int j;
	if (i<1 || i>L->length)
		return false;
	i--;						//将顺序表位序转化为elem下标
	e = L->data[i];
	for (j = i; j < L->length - 1; j++)	//将data[i]之后的元素前移一个位置
		L->data[j] = L->data[j + 1];
	L->length--;				//顺序表长度减1
	return true;
}


注:

  • 同上,删除之后,后面的元素就得往前靠一靠,把空位补上
  • 时间复杂度:同上

进阶应用

2.1 删除

题:删除表中所有值等于x的元素

void delnode1(SqList *&L,ElemType x)
{
	int k=0,i;  //k记录值不等于x的元素个数
	for  (i=0;i<L->length;i++) 
		if (L->data[i]!=x)
		{
			L->data[k]=L->data[i];
			k++;    //不等于x的元素增1
		}
	L->length=k;  //顺序表L的长度等于k
}

思路:这个方法定义了两个指向,i是原来的,k是修改后的;i扫描元素,如果不等于x就把元素给k,如果等于就不给。一个扫描一个建表

void delnode2(SqList *&L,ElemType x)
{ 
	int k=0,i=0; //k记录值等于x的元素个数
	while (i<L->length) 
	{
		if (L->data[i]==x) 
			k++;
		else 
			L->data[i-k]=L->data[i]; //当前元素前移k个位置
		i++;
	}
	L->length-=k;	//顺序表L的长度递减k
}

思路:定义k为移动跨度,如果有两个值等于x,则后面的元素就需要向前补两格

2.2合并表

把表A和表B按从小到大的顺序合并成一个表C,A表B表的元素个数分别为mn
表A,表B均为非递减

void Combination(SqList* L1, SqList* L2, SqList* L3) {
	int i = 0, j = 0, k = 0;
	while ((i != L1->length) && (j != L2->length)) {  //判断AB表是否为空表
		if (L1->data[i] > L2->length) {
			L3->data[k++] = L2->data[j++];
		}
		else if (L1->data[i] == L2->length)
		{
			L3->data[k++] = L2->data[j++];			//相同保留一个
			i++;
		}
		else {
			L3->data[k++] = L1->data[i++];
		}
		L3->length++;
	}
	// 合并没结束,把剩余的加上去
	while (i < L1->length) {
		L3->data[k++] = L1->data[i++];
		L3->length++;
	}
	while (j < L2->length) {
		L3->data[k++] = L2->data[j++];
		L3->length++;
	}
}
2.3 逆置

实现顺序表逆置,

int ListOppose(SqList* L) {
	int i;
	ElemType x;  //数据元素类型

	for (i = 0; i < L->length / 2; i++) {
		x = L->data[i];
		L->data[i] = L->data[L->length - i - 1];
		L->data[L->length - i - 1] = x;
	}

	return 1;
}

void Reverse(int R[], int from, int to) {
	int i;
	int temp;
	for (i = 0; i < (to - from + 1); i++) {
		temp = R[from + i];
		R[from + i] = R[to - i];
		R[to - i] = temp;
	}
}
2.4 基准分割

以第一个元素为基准,小的在前,大的在后

void move2(SqList *&L)
{	int i=0,j=L->length-1;
	ElemType base=L->data[0];	//以data[0]为基准
	while (i<j)  				//从顺序表两端交替向中间扫描,直至i=j为止
	{	while (j>i && L->data[j]>base)
			j--;				//从右向左扫描,找一个小于等于base的data[j]
		L->data[i]=L->data[j];	//找到这样的data[j],放入data[i]处
		while (i<j && L->data[i]<=base)
			i++;				//从左向右扫描,找一个大于base的记录data[i]
		L->data[j]=L->data[i];	//找到这样的data[i],放入data[j]处
	}
	L->data[i]=base;
	printf("i=%d\n",i);
}
2.5 类型划分

将所有的奇数移动到偶数前面

void swap(int &x,int &y)				//交换x和y
{	int tmp=x;
	x=y; y=tmp;
}

void move1(SqList *&L)
{
	int i=0,j=L->length-1;
	while (i<j)
	{
		while (i<j && L->data[j]%2==0)
			j--;					//从右向左扫描,找一个奇数元素
		while (i<j && L->data[i]%2==1)
			i++;					//从左向右扫描,找一个偶数元素
		if (i<j)					//若i<j,将L->data[i]和L->data[j]交换
			swap(L->data[i],L->data[j]);
	}
}

void move2(SqList *&L)
{	int i=-1,j;
	for (j=0;j<=L->length-1;j++)
		if (L->data[j]%2==1)		//j指向奇数时
		{
			i++;					//奇数区间个数增1
			if (i!=j)				//若i、j不相等
				swap(L->data[i],L->data[j]);//L->data[i]和L->data[j]交换
		}
}
  • 解法一:定义两个指针i,j,左边奇数区域的i从左向右去找偶数,右边偶数区域的j从右向左去找奇数,都找到了就对调
  • 解法二:i初始负1,代表为奇数区域的个数为0个,j从左向右去找奇数,找到了奇数就和i指向的奇数换一下,换完之后j++,指向下一个

题目:

在一个长度为n的顺序表中删除第i个元素,需要向前移动()个元素

  • A n-i

  • B n-i+1

  • C. n-i-1

  • D. i+1

答案:A

在长度为n的顺序表中的任何一个位置插入元素的概率相等,则插入一个元素

所需移动的元素的平均个数是()

  • A n/2

  • B. n

  • C. n+1

  • D. (n+1)/2

注:插入位置有n+1个

答案:A

在表长为n的顺序表中,当在任何位置删除一个元素的概率相同时,删除一个

元素所需移动的元素的平均个数为

  • A. (n-1)/2

  • B. n/2

  • C. (n+1)/2

  • D. n

答案:A

在一个长度为n的线性表中顺序查找值为x的元素,查找时的平均查找长度(即x与元素的平均比较次数,假定查找每个元素的概率相等)为

  • A n
  • B (n+1)/2
  • C n/2
  • D (n-1)/2

答案:B

-1

  • D. i+1

答案:A

在长度为n的顺序表中的任何一个位置插入元素的概率相等,则插入一个元素

所需移动的元素的平均个数是()

  • A n/2

  • B. n

  • C. n+1

  • D. (n+1)/2

注:插入位置有n+1个

答案:A

在表长为n的顺序表中,当在任何位置删除一个元素的概率相同时,删除一个

元素所需移动的元素的平均个数为

  • A. (n-1)/2

  • B. n/2

  • C. (n+1)/2

  • D. n

答案:A

在一个长度为n的线性表中顺序查找值为x的元素,查找时的平均查找长度(即x与元素的平均比较次数,假定查找每个元素的概率相等)为

  • A n
  • B (n+1)/2
  • C n/2
  • D (n-1)/2

答案:B

其他:

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐沐沐沐沐雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值