408数据结构学习笔记——顺序表

目录

1.线性表的定义

2.线性表的基本操作

3.线性表的顺序存储表示

4.顺序表

4.1.顺序表的定义

4.1.1.顺序表的静态分配

4.1.2.顺序表的动态分配

4.2.顺序表的基本操作

4.2.1.顺序表的插入操作

4.2.2.顺序表的删除操作

4.2.3.顺序表的按值查找操作

5.王道课后题​


1.线性表的定义

线性表是具有相同特性(每个数据元素所占空间一样大n)的数据元素的一个有限序列

例如:(a1,a2,a3,....ai,....an)

其中a1为起始节点(表头元素),an为终端节点(表尾元素)。每个元素都有且仅有一个直接前驱(第一个元素除外),每个元素都有且仅有一个直接后继(最后一个元素除外)。n为表长,n=0时为空表。

2.线性表的基本操作

InitList(&L):初始化表。构造一个空的线性表

Length(L):求表长。返回线性表L的长度,即L中数据元素的个数

LocateElem(L,e):按值查找。在L中查找给定值的元素

GetElem(L,i):按位查找。在L中查找第i个元素的值

ListInsert(&L,i,e):插入。在L中第i个位置插入e

ListDelete(&L,i,&e):删除。删除L中的第i个位置的元素e,并把e的值带回来

PrintList(L):输出。按顺序输出L的所有元素的值

Empty(L):判断表空。若空,返回True;若不空,返回False

DestroyList(&L):销毁。销毁线性表,并且释放该表的内存空间

3.线性表的顺序存储表示

逻辑上相邻的元素存储在物理上也相邻的位置,依次存储地址连续可以实现随机存储。因此,所有元素的存储位置可以由第一个元素的存储位置计算而得:LOC(ai) = LOC(a1) + (i - 1) * 每个元素存储空间

逻辑位序和物理位序相差1(数组特性)

//线性表定义
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
typedef struct{
    Elemtype elem[LIST_INIT_SIZE];//数据类型
    int length;//当前长度
}SqList;
#define MAXSIZE 10000    //图书表可能达到的最大长度
typedef struct {    //图书信息定义
    char no[20];    //图书ISBN
    char name[50];    //图书名字
    float price;    //图书价格
}Book;
typedef struck {
    Book *elem;    //存储空间的基地址
    int length;    //图书表中当前图书个数
}Sqlist;    //图书表的顺序存储结构类型为SqList

4.顺序表

4.1.顺序表的定义

4.1.1.顺序表的静态分配

#include<stdio.h>
#define Maxsize 10    //定义最大长度
typedef struct{
    int data[Maxsize];    //用静态数组存放数据元素
    int length;    //顺序表的当前长度
}sqList;    //顺序表的类型定义

//基本操作——初始化一个顺序表
void initList(sqList &L){
    for (int i = 0; i < Maxsize; i++){
        L.data[i] = 0;    //将所有数据元素设置为默认初始值
    L.length = 0;    //顺序表初始长度为0
}
int main(){
    sqList L;    //申明一个顺序表L
    inList(L);    //初始化顺序表L
    //.....后续操作
    return 0;
}

需要对数组元素进行初始化,防止有脏数据

4.1.2.顺序表的动态分配

SqList L;    //定义顺序表L
L.data = (ElemType*)malloc(sizeof(Elemtype)*MaxSize);    //申请内存空间

先用sizeof函数计算出Elemtype的单位空间,乘以MaxSize,即总数,得到总共所需的内存空间,再通过(ElemType*)强制转换为ElemType*类型的数据

#define initList 10    //顺序表的初始长度
typedef struct{
    Elemtype *data;    //指示动态分配数组的指针
    int Maxsize;    //顺序表的最大容量
    int length;    //顺序表的当前长度
}sqList;
//用malloc函数申请一片连续的存储空间,返回的是首地址,用指针去接收它
sqList L;
L.data = (ElemType*)malloc(sizeof(Elemtype)*initSize);
#define initSize 10    //默认的最大长度
typedef struct{
    int* data;    //指示动态分配的指针
    int maxSize;    //顺序表的最大容量
    int length;    //顺序表的当前长度
}sqList;

void initList(sqList &L){
    //用malloc申请一片连续的存储空间
    L.data = (int*)malloc(initSize * sizeof(int));
    L.length = 0;
    L.maxSize = initSize;
}

//增加动态数组长度
void increaseSize(sqList &L, int len){
    int *p = L.data;
    L.data = (int*)malloc((L.Maxize + len) * sizeof(int));
    for (int i = 0; i < L.len; i++){
        L.data[i] = p[i];    //将数据复制到新区域
    }
    L.maxSize = L.maxSize + len;    //将顺序表最大长度增加len
    free(p);    //释放原来的空间
}

int main(){
    sqList L;    //申明一个顺序表L
    initList(L);    //初始化顺序表L
    //往L中加入元素
    increaseSize(L, 7);
    return 0;
}

4.2.顺序表的基本操作

4.2.1.顺序表的插入操作

bool insertElem(sqList& L, int i, int e) {
    //插入位置非法返回false
	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];
	}
    //在第i个位置插入元素,但是因为是数组,所以第i个位置的数组下标为i - 1
	L.data[i - 1] = e;
    //数组长度+1
	L.length++;
	return true;
}

4.2.2.顺序表的删除操作

bool deleteElem(sqList& L, int i, int& e) {
	//判断删除位置是否非法,不用判断是否顺序表是否为空表
	//空表情况下L.length = 0
	if (i < 1 || i > length + 1) return false;
	//通过引用方式取出元素
	e = L.data[i - 1];
	//从i开始遍历顺序表,并且依次向前移动
	for (int j = i; j < L.length; j++) {
		L.data[j - 1] = L.data[j];
	}
	//不用将最后一个元素归零,因为L.length--,使得最后一个元素不在访问范围之内
	L.length--;
	return true;
}

4.2.3.顺序表的按值查找操作

int locateElem(sqList L, int e) {
    //遍历数组元素,如果当前元素和e相等,返回它的位序,即下标+1
	for (int i = 0; i < L.length; i++) {
		if (e == L.data[i]) return i + 1;
	}
	//如果没找到该元素,则return 0表示未找到
	//因为正常情况下返回值只可能是1 ~ L.length的数字
	return 0;
}

5.王道课后题

bool deleteMinuteElem(sqList& L, Elemtype& e) {
	//表空返回false
	if (L.length == 0) return false;
	//minnuteNum记录表中最小值,locateMinuteNum记录其下标
	int minuteNum = L.data[0], locateMinuteNum = 0;
	//遍历数组,找到最小值
	for (int i = 0; i < L.length; i++) {
		if (L.data[i] < minuteNum) {
			minuteNum = L.data[i];
			locateMinuteNum = i;
		}
	}
	//带回最小值
	e = minuteNum;
	//将表尾元素赋值给被删除下标元素
	L.data[locateMinuteNum] = L.data[L.length - 1];
	//表长度--
	L.length--;
	return true;
}

void reverseSq(sqList& L) {
	//遍历前半数组元素,并进行跟后半数组元素通过temp进行对调
	for (int i = 0, j = L.length - 1, temp = 0; i < L.length / 2; i++, j--) {
		temp = L.data[i];
		L.data[i] = L.data[j];
		L.data[j] = temp;
	}
}

void deleteElem(sqList& L, Elemtype x) {
	//遍历数组,重新排列不等于x的元素,并记录其个数
	for (int i = 0, j = 0; i < L.length; i++) {
		if (L.data[i] != x) {
			L.data[j] = L.data[i];
			j++;
		}
	}
	L.length = j;
}

bool deleteStoT(sqList& L, Elemtype s, Elemtype t) {
	//判断s和t是否合法,表是否为空
	if (s >= t || L.length == 0) return false;
	int locateS = 0, locateT = 0;
	//找到表中第一个大于s的元素,如果没有,则返回false
	for (; locateS < L.length && L.data[locateS] < s; locateS++) {
		if (locateS = L.length) return false;
	}
	//找到表中第一个大于t的元素
	for (; locateT < L.length && L.data[locateT] <= t; locateT++);
	//将大于t的元素依次前移
	for (; locateT <= locateS; locateT++, locateS++) {
		L.data[locateS] = L.data[locateT];
	}
	//修改表长
	L.length = locateS;
	return true;
}

bool deleteStoT(sqList& L, Elemtype s, Elemtpye t) {
	//判断输入数据是否合法,表是否为空
	if (s >= t || L.length == 0) return false;
	//遍历数组,如果数字全小于s,则返回false
	for (int i = 0; L.data[i] < s; i++) {
		if (i >= L.length) return false;
	}
	int j = 0;
	//遍历数组,并不在范围内的元素
	for (int i = 0; i < L.length; i++) {
		if (L.data[i] < s || L.data[i] > t) {
			L.data[j] = L.data[i];
			j++;
		}
	}
	//修改数组的长度
	L.length = j;
	return true;
}

bool deleteSame(sqList& L) {
	//判断表空
	if (L.length == 0) return false;
	int i, j;
	for (i = 0, j = 1; j < L.length;) {
		//当前两个元素不相等,将后元素前移,两个指针后移
		if (L.data[i] != L.data[j]) {
			L.data[i + 1] = L.data[j];
			i++;
			j++;
		}
		//相等,则后移找到第一个不相等的元素
		else {
			j++;
		}
	}
	//修改表长
	L.length = i + 1;
	return true;
}

bool mergeSq(sqList& L1, sqList& L2, sqList& L3) {
	//判断合并后长度是否大于最大表长
	if (L1.length + L2.length > L3.maxSize) return false;
	int i, j, k;
	//遍历顺序表,将更小的元素插入到新表中
	for (i = 0, j = 0, k = 0; i < L1.length && j < L2.length; k++) {
		if (L1.data[i] <= L2.data[j]) L3.data[k] = L1.data[i++];
		else L3.data[k] = L2.data[j++]; 
	}
	//插入剩余元素
	while (j < L2.length) L3.data[k++] = L2.data[j++];
	while (i < L1.length) L3.data[k++] = L1.data[i++];
	//修改表长
	L3.length = k;
	return true;
}

//将数组元素逆置
void reverse(Elemtype* arr, int left, int right, int arrSize) {
	if (left >= right || right > arrSize) return;
	int mid = left + right - 1;
	//便利数组元素,通过temp变量进行逆置
	for (int i = left, j = right - 1; i <= mid; i++, j--) {
		Elemtype temp = arr[left + i];
		arr[left + i] = arr[right - 1];
		arr[right - 1] = temp;
	}
}
void exchange(Elemtype* arr, int m, int n. int arrSize) {
	//将整个数组逆置
	reverse(arr, 0, m + n - 1, arrSize);
	//前n个元素逆置
	reverse(arr, 0, n - 1, , arrSize);
	//后m个元素逆置
	reverse(arr, n, m + n - 1, arrSize);
}

void searchInsertExhange(sqList& L, Elemtype x) {
	int low = 0, high = L.length - 1;
	//折半查找x
	while (low <= high) {
		mid = (high + low) / 2;
		if (L.data[mid] == x) {
			break;
		}
		else if (L.data[mid] < x) low = mid + 1;
		else if (L.data[mid] > x) high = mid - 1;
	}
	//当前元素为x且它不是表中最后一个元素,与后继进行交换
	if (L.data[mid] == x && mid != length - 1) {
		Elemtype t = L.data[mid];
		L.data[mid] = L.data[mid + 1];
		L.data[mid + 1] = t;
	}
	//表中没有x元素
	if (low > high) {
		int i;
		//大于x的元素依次后移,并插入x元素
		for (i = L.length - 1; i > high; i--) L.data[i + 1] = L.data[i];
		L.data[i+ 1] = x;
		L.length++;
	}
}

//逆置数组
void reverse(Elemtype* arr, int left, int righ) {
	int i, j;
	for (i = 0, j = right; i <= (left + right) / 2; i++,j--) {
		Elemtype t = arr[left + i];
		arr[left + i] = arr[j];
		arr[j] = t;
	}
}
void exchange(Elemtype* arr, int p, int n) {
	//前p个元素逆置
	reverse(arr, 0, p - 1, arrSize);
	//后n - p个元素逆置
	reverse(arr, p, n - 1, arrSize);
	//整个数组逆置
	reverse(arr, 0, n - 1, arrSize);
}
#2
void Swap(int &i, int &j) {	//交换元素
	int temp = i;
	i = j;
	j = temp;
}
void MoveElem(int R[], int p, int n) {
	int i, j;	//i用于从表头开始遍历元素,j用于从表尾开始遍历远古三
	for (i = 0, j = n - 1; i < j; i++, j--) {	//交换i和j的元素
		swap(R[i], R[j]);
	}
	for (i = 0, j = n - p - 1; i < j; i++, j--) {
		swap(R[i], R[j]);
	}
	for (i = n - p, j = n - 1; i < j; i++, j--) {
		swap(R[i], R[j]);
	}
}

int getNum(int A[], int B[]) {
	int i, j, k, length, temp;
	//求数组元素个数
	for (length = 0; A[length] != NULL; length++);
	//取得中位数
	for (i = 0, j = 0, k = 0; k < length; k++) {
		if (A[i] <= B[j]) temp = A[i++];
		else temp = B[j++];
	}
	return temp;
}
#2
int LocateMid(int s1[], int s2[], int len1, int len2) {
	int mid = (len1 + len2) / 2;	//mid记录中位数是两个数列总数的第几个数
	int i = 0, j = 0;	//i和j分别用于遍历s1和s2
	int temp = 0;
	while (mid > 0) {
		if (s1[i] > s2[j]) {
			temp = s2[j];
			j++;
		}
		else {
			temp = s1[i];
			i++;
		}
		mid--;
	}
	return temp;
}

int keyNum(int A[], int n) {
	//申明一个包含n个元素的数组
	int arr[n] = { 0 };
	//循环遍历数组,得到相应元素的出现次数
	for (int i = 0; i < n; i++) {
		int j = A[i];
		arr[j]++;
	}
	//遍历数组,求出最大值
	int max = -1, temp = -1;
	for (int i = 0; i < n; i++) {
		if (arr[i] > max) {
			max = arr[i];
			temp = i;
		}
	}
	//判断最大值是否大于n/2
	if (max > n / 2) return temp;
	else return -1;
}

int minNum(int arr[], int n) {
	int* A, i;
	//申明数组,并且初始化
	A = (int*)malloc(sizeof(int) * n);
	memset = (A, 0, sizeof(int) * n);
	//遍历数组arr,如果其值为整数,则在数组B中标记
	for (i = 0; i < n; i++) {
		if (arr[i] > 0 && arr[i] <= n) {
			A[arr[i] - 1] = 1;
		}
	}
	//遍历数组B,如果当前元素值为0,跳出循环
	for (i = 0; i < n; i++) {
		if (A[i] == 0) {
			break;
		}
	}
	return i + 1;
}

#define INT_MAX 0x7fffffff
//计算绝对值
int calculate(int a) {
	if (a < 0) return -a;
	else return a;
}
//判断三个数中的最小值
int getMin(int a, int b, int c) {
	int min = a;
	if (b < min) min = b;
	if (c < min) min = c;
	return min;
}
int minDis(int a[], int n, int b[], int m, int c[], int x) {
	int res = INT_MAX;
	int i, j, k;
	//遍历数组
	for (i = 0, j = 0, k = 0; i < n && j < m && k < x;) {
		//计算|a - b| + |b - c| + |c - a|,并判断是否比当前存储的D更小
		int temp = calculate(a[i] - b[j]) + calculate(b[i] - c[k]) + calculate(c[j] - a[k]);
		if (temp < res) res = temp;
		//判断最小值在哪个数组中,并使其下标右移
		int min = getMin(a[i], b[j], c[k]);
		if (min == a[i]) i++;
		else if (min == b[j]) j++;
		else k++;
	}
	return res;
}
#2
int GetDis(int a, int b) {
	int c = a - b;
	if (c >= 0) return c;
	else return -c;
}

int MinDis(int s1[], int s2[], int s3[], int len1, int len2, int len3) {
	int i, j, k;
	int res = INT_MAX;
	int current;
	for (i = 0; i < len1; i++) {
		for (j = 0; j < len2; j++) {
			for (k = 0; k < len3; k++) {
				current = GetDis(s1[i], s2[j]) + GetDis(s2[j], s3[k]) + GetDis(s3[k], s1[i]);
				if (current < res) res = current;
				else if (current == 0) return current;
			}
		}
	}
	return res;
}

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值