23王道数据结构 C2线性表笔记

CHAPTER 2 线性表

算法题命题重点,实现容易代码量少,要求最优性能。

2.2 线性表的顺序表示

定义

特点:表中元素逻辑顺序及其物理顺序相同

假定元素类型为ElemType,线性表顺序存储类型描述为:

#define MaxSize 50
typedef struct{
	ElemType data[MaxSize]; // 顺序表元素
	int length ; // 顺序表长度
}SqList;

这是静态分配,同样可以动态分配

#define InitSize 50
typedef struct{
	ElemType *data; // 指示动态分配数组的指针
	int MaxSize, length ; // 数组最大容量和当前个数
}SeqList;

C++ 初始动态分配的语句:L.data = new ElemType[InitSize] ;
注意:动态分配同样属于顺序存储结构,而非链式存储,依然是随机存储方式,只是分配的空间大小可以在运行时动态决定。

基本操作实现

  • 插入操作 O(n)
bool ListInsert(SqList &L, int i, ElemType e){ 
	if(i < 1 || i > L.length + 1) return false ;
	if(L.length >= MaxSize) return false ;
	for(int j = L.length ; j >= i ; j --){
		L.data[j] = L.data[j - 1] ;
	}
	L.data[i - 1] = e ; //第 i 个元素下标为 i - 1 
	L.length ++ ;
	return true ;
}

e 插到第 i 个元素的位置。


  • 删除操作 O(n)
bool(SqList& L, int i, ElemType e){
	if(i < 1 || i > L.length) return false ;
	e = L.data[i - 1] ;
	for(int j = i ; j < L.length ; j ++){
		L.data[j - 1] = L.data[j] ;
	}
	L.length -- ;
	return true ;
}

删除第 i 个位置的元素,并返回 e 。


  • 按值查找
int Locate(SqList& L, ElemType e){
	int i ;
	for(int i = 0 ; i < L.length ; i ++){
		if(L.data[i] == e) return i + 1 ;
	}
	return 0 ;
}

返回第一个值为 e 的元素元素下标。

习题

单选

Q:线性表的顺序存储结构是一种随机存取的存储结构
存取方式指的是读写方式。

请添加图片描述

请添加图片描述


01

  • 从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。空出的位置由最后一个元素填补,若空,则显示错误信息并退出。
bool FindMinDel(SqList& L, ElemType e){ // 01
	if(L.length == 0) return false ;
	e = L.data[0]; int index = 0 ;
	for(int i = 1 ; i < L.length ; i ++){
		if(L.data[i] < e) {
			index = i ;
			e = L.data[i] ;
		} 
	}
	L.data[index] = L.data[length - 1] ;
	L.length -- ;
	return true ;
}

02

  • 将顺序表L所有元素逆置,要求算法空间复杂度O(1)。
void SwapAll(SqList& L){
	int l = 0 , r = L.length - 1 ;
	while(l < r){ //swap()
		ElemType tmp = L.data[l] ;
		L.data[l] = L.data[r] ;
		L.data[r] = tmp ;
		l ++ ; r -- ;
	}
	return ;
}

双指针,或者swap(L.data[i] , L.data[L.length - i - 1])


03
  • 删除线性表中所有值为x的数据元素,要求时O(n),空O(1)
void (SqList& L, ElemType x){ // visit unx
	int k = 0  ;
	for(int i = 0 ; i < L.length ; i ++){
		if(L.data[i] != x){
			L.data[k] = L.data[i] ;
			k ++ ;
		} 
	}
	L.length = k ;
}

法一,记录不是x的数个数 k ,每次把第 i 个移到第 k 个位置。有点妙。

void (SqList& L, ElemType x){ // visit x
	int k = 0  ;
	for(int i = 0 ; i < L.length ; i ++){
		if(L.data[i] == x) k ++ ;
		else L.data[i - k] = L.data[i] ;
	}
	L.length -= k ;
}

法二,记录x的个数k,不是x的往前挪k个位置。


04

  • 有序顺序表中删除其值在给定值 s,t 之间(s < t)的所有元素,若s,t不合理或表空,返回错误信息并退出运行。
bool Delst(SqList& L, ElemType s, ElemType t){
	if(s >= t || L.length == 0) return false ;
	for(int i = 0 ; i < L.length ; i ++){
		int k = 0 ;
		if(L.data[i] < s || L.data[i] > t){
			L.data[k] = L.data[i] ;
			k ++ ;
		}
	}
	L.length = k ;
	return true ;
}

由于是有序顺序表,s 到 t 是一整段,并不需要用到 03 的方法。

bool Delst(SqList& L, ElemType s, ElemType t){
	if(s >= t || L.length == 0) return false ;
	int index , num = 0;
	for(int i = 0 ; i < L.length ; i ++){
		if(L.data[i] >= s){
			index = i ; break ;
		}
	}
	for(int i = indexs ; i < L.length ; i ++){
		if(L.data[i] > t){
			L.data[index] = L.data[i] ;
			index ++ ;
			num ++ ;
		}
	}
	L.length -= num ;
	return true ;
}

找到第一个和最后一个s,t间的数,后继向前挪。
虽然答案用的这种方法,但感觉不如 03 好使,反正都是O(n)。


06

  • 有序顺序表中删除所有其值重复的元素
bool DelRepetion(SqList& L){
	if(L.length == 0) return false ;
	int k = 1 ;
	for(int i = 1 ; i < L.length() ; i ++){
		if(L.data[i] != L.data[i - 1]){
			L.data[k] = L.data[i] ;
			k ++ ;
		}
	}
	L.length = k ;
	return true ;
}

07

  • 将两个有序顺序表合成一个新的有序顺序表
void Bin(SqList a, SqList b, SqList& L){
	int i = 0 , j = 0, k = 0 ;
	while(i < a.length || j < b.length){
		if (i < a.length && j < b.length){
			if (a.data[i] < b.data[j]){
				L.data[k] = a.data[i] ;
				i ++ ; k ++ ;
			}
			else {
				L.data[k] = b.data[j] ;
				j ++ ; k ++ ;
			}
		}
		else if (i < a.length){
			L.data[k] = a.data[i] ;
			i ++ ; k ++ ;
		}
		else (j < b.length){
			L.data[k] = b.data[j] ;
			j ++ ; k ++ ;
		}
	}
	L.length = k ;
}

08
  • 已知在 A[m,n] 中依次存放两个线性表 a[m] b[n] ,编写一个函数,互换ab位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值