目录
1.线性表的定义
2.线性表的基本操作
3.线性表的顺序存储表示
4.顺序表
4.1.顺序表的定义
4.1.1.顺序表的静态分配
4.1.2.顺序表的动态分配
4.2.顺序表的基本操作
4.2.1.顺序表的插入操作
4.2.2.顺序表的删除操作
4.2.3.顺序表的按值查找操作
5.王道课后题
线性表是具有相同特性(每个数据元素所占空间一样大n)的数据元素的一个有限序列
例如:(a1,a2,a3,....ai,....an)
其中a1为起始节点(表头元素),an为终端节点(表尾元素)。每个元素都有且仅有一个直接前驱(第一个元素除外),每个元素都有且仅有一个直接后继(最后一个元素除外)。n为表长,n=0时为空表。
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):销毁。销毁线性表,并且释放该表的内存空间
把逻辑上相邻的元素存储在物理上也相邻的位置,依次存储,地址连续,可以实现随机存储。因此,所有元素的存储位置可以由第一个元素的存储位置计算而得: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
#include
#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;
}
需要对数组元素进行初始化,防止有脏数据
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;
}
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;
}
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;
}
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;
}
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;
}