【数据结构二】线性表之顺序表 概念和习题:两个有序数组合并 调换数组某部分得到目标顺序 有序单调递增线性表的最快查找与替换 找出主元素 找出中位数

目录:

【数据结构一】逻辑结构,物理结构和数据运算 算法时间复杂度

前言:

线性表是逻辑结构,实现线性表的是存储结构,可以是顺序存储(顺序表,例如数组)也可以是链式存储(单链表,双链表,循环链表,静态链表(利用数组实现,特点依然是逻辑相邻,物理存储不一定相邻))

数据结构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.调换数组某部分得到目标顺序

已知在一维数组A[m+n]A[m+n]中依次存放a1,a2,a3,am)(b1,b2,bn)(a1,a2,a3……,a_m) 和(b1,b2,……b_n)编写函数交换两者位置得到(b1,b2,bn)a1,a2,a3,am)(b1,b2,……bn)和(a1,a2,a3……,a_m)
思路: 先逆置得到:bn,bn1,,b2,b1)(am,am1,a2,a1)(bn,bn-1,……,b2,b1) 和(a_m,a_{m-1},……a2,a1),他们各自再进行一次调换,也就是前n个逆置调换位置,后m个逆置调换位置,就得到(b1,b2,bn)a1,a2,a3,am)(b1,b2,……bn)和(a1,a2,a3……,a_m)
输入: mnm 和 n 的值和数组

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.有序单调递增线性表的最快查找与替换

有序单调递增线性表,设计算法用最少时间在表中查找数值为 xx 的元素,找到后交换它和后继位置。
如果找不到,就插入表中,并使得表依然有序。
输入: 数组大小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,BA,B,求他们俩的中位数,尽量时间空间上都要简单:
例如:A{4,6,8,10,15}B{12,16,18,20,25}A\{ 4,6,8,10,15\} B\{12,16,18,20,25\} 的中位数就是 1212

思路:
分别求序列A,BA,B的中位数a,ba,b 求序列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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章