目录:
前言:
线性表是逻辑结构,实现线性表的是存储结构,可以是顺序存储(顺序表
,例如数组)也可以是链式存储(单链表,双链表,循环链表,静态链表
(利用数组实现,特点依然是逻辑相邻,物理存储不一定相邻))
数据结构c语言定义:
//静态分配:
#define MaxSize 50
typedef struct{
int data[MaxSize];
int length;
}seqList;
动态分配:
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef struct
{
int *data;
int length;
} seqList;
int main()
{
seqList L;
L.length=MaxSize;
//注意,malloc分配空间后,并不能初始化为0
//calloc却在申请后,对空间逐一进行初始化,并设置值为0;
//L.data=(int*)calloc(L.length,sizeof(int));
L.data=(int*)malloc(sizeof(int)*L.length);
return 0;
}
练习题:
1.两个有序数组合并
两个 有序
顺序表合并为一个新的有序顺序表,函数返回结果顺序表:
c代码:
#include <stdio.h>
#include <stdlib.h>
int * merge_array(int a[],int b[],int len_a,int len_b)
{
int len_c=len_a+len_b;
int *c=(int*)malloc(sizeof(int)*len_c);
int i=0,j=0,k=0;
while(i<len_a&&j<len_b)
{
if(a[i]<b[j]) //保存两者中小的那一个
{
c[k]=a[i];
i++,k++;
}
else
{
c[k]=b[j];
j++,k++;
}
}
//保存剩下的一个数组里的全部元素
while(i<len_a)
{
c[k]=a[i];
i++,k++;
}
while(j<len_b)
{
c[k]=b[j];
j++,k++;
}
return c;
}
int main()
{
int a[5]= {1,2,3,4,5};
int b[5]= {3,4,5,6,7};
int* result=merge_array(a,b,5,5);
int i=0;
for(; i<10; i++)
{
printf("%d ",result[i]);
}
return 0;
}
2.调换数组某部分得到目标顺序
已知在一维数组中依次存放编写函数交换两者位置得到
思路: 先逆置得到:,他们各自再进行一次调换,也就是前n个逆置调换位置,后m个逆置调换位置
,就得到
输入: 的值和数组
4 6
1 2 3 4 5 6 7 8 9 0
输出:
7 8 9 0 1 2 3 4 5 6
5 6 7 8 9 0 1 2 3 4
c代码:
#include <stdio.h>
#include <stdlib.h>
///输入:待处理数组,逆置起始位置,结束位置
void exchangePlace(int A[],int start,int end)
{
int i=start,j=end;
while(i<j)
{
int tmp=A[i];
A[i]=A[j];
A[j]=tmp;
i++,j--;
}
}
//打印数组
void print(int A[],int len)
{
int i=0;
while(i<len)
{
printf("%d ",A[i]);
i++;
}
printf("\n");
}
int main()
{
int m=0,n=0;
scanf("%d %d",&m,&n);
int *A=(int*)malloc(sizeof(int)*(m+n));
int i=0;
for(i=0; i<m+n; i++)
{
scanf("%d",&A[i]);
}
exchangePlace(A,0,m+n-1);
exchangePlace(A,0,n-1);
exchangePlace(A,n,m+n-1);
print(A,m+n);
return 0;
}
3.有序单调递增线性表的最快查找与替换
有序单调递增线性表,设计算法用最少时间在表中查找数值为 的元素,找到后交换它和后继位置。
如果找不到,就插入表中,并使得表依然有序。
输入: 数组大小M,元素x,数组的内容
4 4
1 2 3 5
输出:
1 2 3 4 5
输入:
4 4
1 2 4 6
输出:
1 2 6 4
由于malloc分配空间不进行任何初始化,所以只是交换时会出现一个多余的数,也可以自己先分配一个值来解决这个问题,或者静态初始化数组:
#include <stdio.h>
#include <stdlib.h>
void binary_search_re(int a[],int len,int x)
{
int mid=len/2;
int start=0,end=len-1;
while(start<=end)
{
mid=(start+end)/2;
if(a[mid]>x)
{
end=mid-1;
}
else if(a[mid]<x)
{
start=mid+1;
}
else if(a[mid]==x)
{
//交换x和后面一个元素的位置,如果是最后一个,
break;
}
}
if(a[mid]==x && mid!=len-1)
{
//不是最后一个,才交换位置
int tmp=a[mid];
a[mid]=a[mid+1];
a[mid+1]=tmp;
}
if(start>end) //没找到这个元素,
{
int i=0;
for(i=len-1; i>end; i--)
{
a[i+1]=a[i];//移动mid后面的元素
}
a[i+1]=x;//插入X
}
}
void print(int A[],int len)
{
int i=0;
while(i<len)
{
printf("%d ",A[i]);
i++;
}
printf("\n");
}
int main()
{
int len=0,x=0;
scanf("%d %d",&len,&x);
int *a=(int*)malloc(sizeof(int)*(len+1));
int i=0;
for(i=0; i<len; i++)
{
scanf("%d",&a[i]);
}
binary_search_re(a,len,x);
print(a,len+1);
return 0;
}
4.找出主元素
主元素是出现在数组中,出现次数超过了n/2次的数,
给定一个数组,问是否有主元素。
输入:
0,5,5,3,5,7,5,5
输出:
5
输入
0,5,5,3,5,1,5,7
输出:
无主元素
参考真题: 腾讯2019技术岗笔试 消消乐
只要出现次数最多的那一个数的出现次数小于等于一半就是YES,否则NO
比如:1 1 1 1 1 1 3 3 3 3 4 4
时间复杂度O(1):
扫描数组一次,遇到一个值就计数i=1;如果下一个不是这个值就i减一,如果是这个值就加一;从而有扫描完全组,倘若i>=1说明这个数是主元素。因为如果出现次数大于一半,i的值就一定大于1,请你仔细品品。
空间复杂度也是O(1)
完全没用到任何的栈或者链这类复杂数据结构。这样做题最快而且最方便。
代码:
#include <stdio.h>
#include <stdlib.h>
int detectMainElement(int a[],int len)
{
int count=0,i=0,main_element=a[0];
for(i=1; i<len; i++)
{
if(a[i]==main_element)
count++;
else
count--;
if(count<0)
{
main_element=a[i];
count++;
}
}
if(count>0)
return main_element;
else
return -1;
}
int main()
{
int a[8]= {0,5,5,3,5,5,5,7};
printf("%d",detectMainElement(a,8));
}
5.找出中位数
两个有序等长序列,求他们俩的中位数,尽量时间空间上都要简单:
例如: 的中位数就是
思路:
分别求序列的中位数 求序列A,B的中位数,
1.a=b,则a或者b就是中位数
2.a<b,舍弃A的小的一半(以a为分割点)和B的大的一半(b为分割)
3.a<b,舍弃A的大的一半(以a为分割点)和B的小的一半(b为分割),其中舍弃的部分都要一样长。
注意处理奇数和偶数的情况!!!
由于比较简单,就不放代码了。
还是放一下吧,怎么可以不写代码呢……
#include <stdio.h>
#include <stdlib.h>
///查找中位数
int find_mid_number(int a[],int b[],int len_a,int len_b)
{
int sa=0,sb=0,ea=len_a-1,eb=len_b-1,mid_a=0,mid_b=0;
//表示起始位置,结束位置,中间位置
while(sa<ea||sb<eb)
{
mid_a=(sa+ea)/2;
mid_b=(sb+eb)/2;
if(a[mid_a]==b[mid_b])
{
return a[mid_a];
}
if(a[mid_a]<b[mid_b])
{
if((sa+ea)%2==0) //奇数
{
sa=mid_a;
eb=mid_b;
}
else
{
sa=mid_a+1;
eb=mid_b;
}
}
else
{
if((sa+ea)%2==0) //奇数
{
sb=mid_b;
ea=mid_a;
}
else
{
sb=mid_b+1;
ea=mid_a;
}
}
}
return a[sa]<b[sb]?a[sa]:b[sb];
}
int main()
{
int a[5]={11,13,15,17,19};
int b[5]={2,4,6,8,20};
printf("%d",find_mid_number(a,b,5,5));
return 0;
}