【數據結構二】線性表之順序表 概念和習題:兩個有序數組合並 調換數組某部分得到目標順序 有序單調遞增線性表的最快查找與替換 找出主元素 找出中位數

目錄:

【數據結構一】邏輯結構,物理結構和數據運算 算法時間複雜度

前言:

線性表是邏輯結構,實現線性表的是存儲結構,可以是順序存儲(順序表,例如數組)也可以是鏈式存儲(單鏈表,雙鏈表,循環鏈表,靜態鏈表(利用數組實現,特點依然是邏輯相鄰,物理存儲不一定相鄰))

數據結構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;
}

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