线性表的特点:
(1)同一性,线性表由同类数据元素组成,每一个ai必须属于同一数据类型。
(2)有穷性,由有限个数据元素组成,表长度就是表中数据元素的个数
(3)有序性,线性表中相邻数据元素之间存在着序偶关系<ai,ai+1>
存放线性表的两种基本存储结构:顺序存储结构和链式存储结构
顺序表:表中元素的逻辑顺序与物理顺序相同,通常用数组来描述顺序表
注:线性表中元素的位序从1开始,数组中元素的下标是从0开始的。
静态分配:数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃。
#define MaxSize 50
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];//顺序表的元素
int length;//顺序表的长度
}SqList;//顺序表的类型定义
动态分配:存储数组的空间是在程序执行过程中通过动态存储分配语句分配,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间。
typedef struct {
ElemType* data;//指示动态分配数组的指针
int Maxsize, length;//数组的最大容量和当前个数
}SeqList;
基本操作:
void IncreaseSize(SeqList* L, int len) {
int *p = L->data;
L->data = (ElemType*)malloc((L->Maxsize + len) * sizeof(ElemType));
for (int i = 0; i < L->length; i++) {
L->data[i] = p[i];
}
L->Maxsize = L->Maxsize + len;
free(p);
}
void InitList(SeqList* L) {
L->data = (ElemType*)malloc(InitSize * sizeof(ElemType));
L->length = 0;
L->Maxsize = InitSize;
}
int ListInsert(SqList* L, int i, ElemType e) {
if (i<1 || i>L->length + 1)//判断i是否有效,因为顺序表中数据元素存储是连续的,所以当i=length+2时无效,造成不连续
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;
L->length++;
return 1;
}
int ListDelete(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 1;
}int LocateElem(SqList L, ElemType e) {
int i;
for (i = 0; i <L.length; i++)
if (L.data[i] == e)
return i + 1;
return 0;
}
ElemType GetElem(SqList L, int i) {
return L.data[i - 1];
}
//删最小
int DelMin(SeqList* L, ElemType* e) {
if (L->length = 0)
return 0;
e=L->data[0];
int i;
for (i = 1; i < L->length; i++) {
if (e > L->data[i])
e = L->data[i];
}
L->data[i] = L->data[L->length-1];
L->length--;
return e;
}
//逆置
int Reverse(SeqList* L) {
ElemType temp;
int i;
for (i = 0; i < L->length / 2; i++)
{
temp = L->data[i];
L->data[i] = L->data[L->length - i-1];
L->data[L->length - i - 1] = temp;
}
}
//删所有x顺序表,记录等于x的个数,改变顺序表长度
void DelX(SqList* L,ElemType x) {
int count = 0;//记录值等于x的个数
int i=0;
while (i < L->length) {
if (L->data[i] == x)
count++;
else
L->data[i - count] = L->data[i];
i++;
}
L->length = L->length - count;
}
//
void Del2X(SqList* L, ElemType x) {
int k = 0;
for (int i = 0; i < L->length; i++)
if (L->data[i] != x)
{
L->data[k] = L->data[i];
k++;
}
}
//删值在s和t之间的数,有序顺序表
int DeLST(SqList* L, ElemType s, ElemType t) {
int i, j;
if (s >= t || L->length == 0)
return false;
for (i = 0; i < L->length && L->data[i] < s; i++);//找到大于等于s的第一个元素
if (i >= L->length)
return false;
for (j = i; j < L->length && L->data[j] <= t; j++); //找到大于t的第一个元素
for (; j < L->length; i++, j++)//前移,填补被删元素位置
L->data[i] = L->data[j];
L->length = i;
return true;
}
//删值在s和t之间的数,顺序表
int DELST(SqList* L, ElemType s, ElemType t) {
int i, k=0;
if (s >= t || L->length == 0)
return false;
for (i = 0; i < L->length; i++) {
if (L->data[i] >= s && L->data[i] <= t)
k++;
else
L->data[i - k] = L->data[i];
}
L->length = L->length - k;
return true;
}
//删除有序表中相同元素保留一个
int DELSame(SqList* L) {
if (L->length == 0)
return false;
int i,j;
for (i = 0, j = 1; j < L->length; j++)
if (L->data[i] != L->data[j])//查找下一个与上个元素值不同的元素
L->data[++i]=L->data[j];//找到后,将元素前移
L->length = i + 1;
return true;
}
int Merge(SqList A, SqList B, SeqList* C) {
if (A.length + B.length > C->Maxsize)
return false;
int i = 0, j = 0, k = 0;
while (i < A.length && j< B.length) {
if (A.data[i] <= B.data[j])
C->data[k++] = A.data[i++];
else
C->data[k++] = B.data[j++];
}
while (i < A.length)
C->data[k++] = A.data[i++];
while (j < B.length)
C->data[k++] = B.data[j++];
C->length = k;
return true;
}
//(a1,a2,...an,b1,b2,b3,...bn)转换成(b1,b2,...,bn,a1,a2,a3,...am)1.先将整个数组逆置,然后对bn....逆置,在对am...逆置
void reverse(ElemType A[], int left, int right, int arraySize) {//逆置
if (left >= right || right >= arraySize)
return;
int mid = (left + right) / 2;
for (int i = 0; i < mid - left; i++) {
ElemType temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void Exchange(ElemType A[], int m, int n, int arraysize) {
Reverse(A, 0, m + n - 1, arraysize);
Reverse(A, 0, n - 1, arraysize);
Reverse(A, n, m + n - 1, arraysize);
}
void Binsearch(SqList* L, ElemType x) {
int low = 0, high = L->length - 1;
ElemType t;
int mid,i;
while (low<=high) {
mid = (low + high) / 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;
}
if (L->data[mid] == x && mid != L->length - 1) {//若最后一个元素与mid处的元素相等,便不需要交换
t = L->data[mid];
L->data[mid] = L->data[L->length - 1];
L->data[L->length - 1] = t;
}
if (low > high) {
for (i = L->length - 1; i > high; i--)
L->data[i + 1] = L->data[i];//元素后移
L->data[i+1] = x;
}
}
//ab--->ba(逆置a,在逆置b,在逆置整个数组)时复杂度O(n),空复杂度O(1)
void REverse(int R[], int from, int to) {
int mid,temp,i;
mid = (from + to) / 2;
for (i = 0; i < mid - from; i++)
{
temp = R[from + i];
R[from + i] = R[to - i];
R[to - i] = temp;
}
}
void Converse(int R[], int n, int p) {
REverse(R, 0, p - 1);
REverse(R, p, n - 1);
REverse(R, 0, n - 1);
}
//分别求两个升序序列的中位数,1.若相等则输出 2若A[mid]<B[mid],舍弃A中较小部分,舍弃B较大部分,舍弃长度相同
//3.若A[mid]>B[mid],舍弃A中较大部分,舍弃B较小部分,舍弃长度相同 .重复123,直到两个序列中均只含一个元素为止,较小者为所求中位数
int M_Search(int A[], int B[], int n) {
int s1 = 0, d1 = n - 1, m1, s2 = 0, d2 = n - 1, m2;
while (s1 != d1 || s2 != d2) {
m1 = (s1 + d1) / 2;
m2 = (s2 + d2) / 2;
if (A[m1] == B[m2])
return A[m1];
if (A[m1] < B[m2]) {
if ((s1 + d1) % 2 == 0) {//元素个数为奇数
s1 = m1;//舍弃A中间点以前的部分且保留中间点
d2 = m2;//舍弃B中间点以后的部分且保留中间点
}
else {//元素个数为偶数
s1 = m1 + 1;//舍弃A中间点以前的部分以及中间点
d2 = m2;//舍弃B中间点以后的部分且保留中间点
}
}
else {
if ((s1 + d1)%2==0) {
d1 = m1;
s2 = m2;
}
else {
d1 = m1;
s2 = m2 + 1;
}
}
}
return A[m1] < B[m2] ? A[s1] : B[s2];
}
int Majority(int A[], int n) {
int i, c, count = 1;
c = A[0];
for (i = 1; i < n; i++)
if (A[i] == c)
count++;
else
if (count > 0)
count--;
else
{
c = A[i];
count = 1;
}
if (count < 0)
for (i = count = 0; i < n; i++)
if (A[i] == c)
count++;
if (count > n / 2)
return c;
else
return -1;
}
//找未出现的最小正整数
int FindMissMin(int A[], int n) {
int i, *B;
B = (int*)malloc(sizeof(int) * n);//分配空间
memset(B, 0, sizeof(int) * n);//赋初值为0
for (i = 0; i < n; i++)
if (A[i] > 0 && A[i] <= n)//A[i]的值介于1-n,则标记数组B
B[A[i] - 1] = 1;
for (i = 0; i < n; i++)//扫描数组B,找到目标值
if (B[i] == 0)
break;
return i + 1;//返回结果
}