1. 程式人生 > >線性表之順序表操作(已完結)

線性表之順序表操作(已完結)

考研408資料結構線性表複習;

有任何問題私我

#include<iostream>
#include<algorithm>

const int initlength = 100;     ///順序表的初始長度

using namespace std;

typedef struct
{
    int *data;
    int MaxSize, length;        ///順序表的最大儲存空間,長度;
}SeqList;


///*****順序表基本操作

void initList(SeqList &L, int n = initlength)       ///初始化順序表
{
    L.data = new int [n];
    L.length = 0;
    L.MaxSize = n;
    for(int i=0;i<L.MaxSize;++i)
    {
        cin>>L.data[i];
        L.length++;
    }
}

int Length(SeqList L)           ///返回順序表的長度
{
    return L.length;
}

bool EmptyList(SeqList L)          ///判斷順序表是否為空
{
    if(L.length == 0)
        return true;
    return false;
}

bool ListInsert(SeqList &L, int i, int value)           ///插入元素, i為元素的位置, value為元素的值
{
    if(i<1 || i>L.length+1)
        return false;
    if(i >= L.MaxSize)
        return false;
    for(int j=L.length; j>=i; --j)
        L.data[j] = L.data[j-1];
    L.data[i-1] = value;
    L.length++;
    return true;
}

bool ListDelete(SeqList &L, int i, int &e)          ///刪除元素, i為刪除元素的位置, e為刪除位置元素的值
{
    if(i<1 || i>L.length)
        return false;
    e = L.data[i-1];
    for(int j=i-1; j<L.length-1; ++j)
        L.data[j] = L.data[j+1];
    L.length--;
    return true;
}

int LocateElem(SeqList L, int e)                ///按值查詢第一個元素值為e的位序
{
    for(int i=0; i<L.length; ++i)
    {
        if(e == L.data[i])
            return i+1;
    }
    return 0;
}


void PrintList(SeqList L)           ///列印輸出整個順序表
{
    for(int i=0;i<L.length;++i)
        cout<<L.data[i]<<" ";
    cout<<endl;
}


///***順序表進階操作,帶題目描述

///1.在順序表中刪除具有最小值的元素(假設唯一), 並由函式返回被刪元素的值
///         空出的位置由最後一個元素填補。若順序表為空,顯示錯誤資訊並退出

bool DeleteMinList(SeqList &L, int &e)
{
    if(EmptyList(L))    //if (L.length == 0)
    {
        cout<<"The List is empty, can't delete the min value!"<<endl;
        return false;
    }
    int ListMin = L.data[0];
    int LocalMin = 0;
    for(int i=0;i<L.length;++i)
    {
        if(ListMin > L.data[i])
        {
            ListMin = L.data[i];
            LocalMin = i;
        }
    }
    e = ListMin;
    L.data[LocalMin] = L.data[L.length-1];
    L.length--;
    return true;
}

///2.設計一個高效演算法,將順序表的所有元素逆置,要求演算法的空間複雜度為O(1)
void ReverseList(SeqList &L)
{
    int temp;
    for(int 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;
    }
}

///3.長度為n的順序表L, 編寫一個時間複雜度為O(n), 空間複雜度為O(1), 該演算法刪除線性表中所有值為x的資料元素。
///可為該順序表重新構造

void DeleteEqualElement(SeqList &L, int x)
{
    int k = 0;
    for(int i=0; i<L.length; ++i)
    {
        if(L.data[i] != x)
        {
            L.data[k] = L.data[i];
            k++;
        }
    }
    L.length = k;
}

///或者第二種演算法
/*
void DeleteEqualElement(SeqList &L, int x)
{
    int k=0, i=0;
    while(i<L.length)
    {
        if(L.data[i] == x)
            k++;
        else
            L.data[i-k] = L.data[i];
        i++;
    }
    L.length -= k;
}
*/

///4.從有序順序表中刪除其值在給定值s與t之間(要求s<t)的所有元素,如果s或t不合理或者順序表為空則顯示出錯資訊並退出執行。
/*
bool Delete_s_among_t(SeqList &L, int s, int t)         ///呼叫此函式前請使用sort或者自定義演算法對順序表排序,使之成為有序表
{
    if(s>=t || EmptyList(L))
    {
        cout<<"The function is not exploit,please check your input or if the list is empty.";
        return false;
    }
    int k=0;
    int num=0;
    for(int i=0;i<L.length;++i)
    {
        if(L.data[i] > s && L.data[i] < t)
        {
            num++;
            if(num == 1)
                k = i;
        }
    }
    if(num == 0)
        return false;
    for(int i=k;i<L.length-num;++i)
    {
        L.data[i] = L.data[i+num];
    }
    L.length -= num;
    return true;
}
*/
///王道給出標準演算法
bool Delete_s_among_t(SeqList &L, int s, int t)
{
    if(s>=t || EmptyList(L))
    {
        return false;
    }
    int i, j;
    for(i=0; i<L.length&&L.data[i]<s; i++)
        if(i >= L.length)
            return false;
    for(j=i; j<L.length&&L.data[j]<=t; j++){}
    for(;j<L.length; i++, j++)
        L.data[i] = L.data[j];
    L.length = i+1;
    return true;
}


///5.從順序表中刪除其值在給定值s與t之間(包含s和t, 要求s<t)的所有元素,如果s或t不合理或者順序表為空則顯示錯誤資訊並退出執行。
/*
bool Delete_s_among_t2(SeqList &L, int s, int t)
{
    if(s>=t || EmptyList(L))
    {
        cout<<"The function is not exploit,please check your input or if the list is empty."<<endl;
        return false;
    }
    bool flag = false;
    for(int i=0;i<L.length;++i)
    {
        if(L.data[i]>=s && L.data[i] <= t)
        {
            for(int j=i;j<L.length-1;++j)
                L.data[j] = L.data[j+1];
            L.length--;
            flag = true;
            --i;
        }
    }
    return flag;
}
*/
///王道推薦高效演算法
bool Delete_s_among_t2(SeqList &L, int s, int t)
{
    if(s>=t || EmptyList(L))
    {
        return false;
    }
    int k = 0;
    for(int 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 -= k;
    return true;
}


///6.從有序順序表中刪除所有其值重複的元素,使表中所有元素的值均不同

bool Delete_repeat_value(SeqList &L)
{
    if(EmptyList(L))
        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;
}


///7.將兩個有序順序表合併成一個有序順序表,並由函式返回結果順序表。

SeqList combine_List(SeqList L1, SeqList L2, SeqList &L3)
{
    ///加層判斷,若L3最大儲存空間小於L1+L2的長度,則返回
    int i=0, j=0, k=0;
    while(i<L1.length && j<L2.length)
    {
        if(L1.data[i] < L2.data[j])
        {
            L3.data[k++] = L1.data[i++];
        }
        else
        {
            L3.data[k++] = L2.data[j++];
        }
    }
    while(i<L1.length)
        L3.data[k++] = L1.data[i++];
    while(j<L2.length)
        L3.data[k++] = L2.data[j++];
    L3.length = k;
    return L3;
}
///8.已知在一維陣列A[m+n]中依次存放著兩個線性表,試編寫一個函式,將陣列中兩個順序表的位置互換,即將bn放在an前面

void reverse_list(SeqList &L, int n)
{
    int mid = (L.length)/2;
    for(int i=0;i<mid;++i)
    {
        int t = L.data[i];
        L.data[i] = L.data[L.length-i-1];
        L.data[L.length-i-1] = t;
    }
    mid = (L.length-n)/2;
    for(int i=0; i<mid; ++i)
    {
        int t = L.data[i];
        L.data[i] = L.data[L.length-n-i-1];
        L.data[L.length-n-i-1] = t;
    }
    mid = n/2;
    for(int i=0; i<n/2; ++i)
    {
        int t = L.data[L.length-n+i];
        L.data[L.length-n+i] = L.data[L.length-i-1];
        L.data[L.length-i-1] = t;
    }
}

///王道推薦演算法,由兩個函式構成 個人略微調整了一下
void Reverse_list(SeqList &L, int left, int right)       ///該函式用於進行逆置
{
    if(left >= right || right >= L.length)
        return;
    int mid = (left + right)/2;
    for(int i=0;i<=mid-left;++i)
    {
        int t = L.data[left + i];
        L.data[left+i] = L.data[right-i];
        L.data[right-i] = t;
    }
    //PrintList(L);
}

void Exchange(SeqList &L, int n)
{
    Reverse_list(L, 0, L.length-1);
    Reverse_list(L, 0, L.length-n-1);
    Reverse_list(L, L.length-n, L.length-1);
}


///9.線性表中元素遞增有序且按照順序儲存於計算機內,要求設計一演算法完成用最少時間在表中查詢數值為x的元素,
///若找到後將其與後繼元素位置相交換,若找不到則將其插入表中並使表中元素仍遞增有序。
void mid_find(SeqList &L, int l, int r, int key)        ///查詢演算法採取二分
{
    if(l >= r)
        return;
    int mid;
    while(l<=r)
    {
        mid = (l + r)/2;
        if(L.data[mid] == key)
            break;
            ///進行交換操作
        else if(L.data[mid] > key)
            r = mid - 1;
        else
            l = mid + 1;
    }
    //cout<<mid<<endl;
    //cout<<l<<" "<<r<<endl;
    if(L.data[mid] == key && mid != L.length-1)
    {
        int t = L.data[mid+1];
        L.data[mid+1] = L.data[mid];
        L.data[mid] = t;
    }
    if(l>r)
    {
        for(int i=L.length;i>l;--i)
            L.data[i] = L.data[i-1];
        L.data[l] = key;
        L.length++;
    }
}


///10.設將n個證書存放在一維陣列R中,試實際一個在時間和空間兩方面都儘可能高效的演算法。
///將R中儲存的序列迴圈左移p個位置,即將R中的資料由(X0, X1, ...Xn-1)變換為(Xp, Xp+1, ....Xn-1, X0, X1..., Xp-1)
///與8題相同思路


///11.一個長度為L的升序序列S, 處在第[L/2]個位置的數稱為S的中位數。現在有兩個等長序列A和B,
///試設計一個時間和空間都儘可能高效的演算法,找出兩個序列A和B的中位數

///演算法描述:分別求兩序列的中位數a和b。
///1.若a=b, 則結束,a或b即為所求中位數
///2.若a<b, 則捨棄A中較小一半,同時捨棄B中較大一半, 要求兩次捨棄長度相等
///3.若a>b, 則捨棄A中較大一半,同時捨棄B中較小一半, 要求兩次捨棄長度相等
///在保留的兩個升序序列中,重複過程123, 知直到兩個序列中只含一個元素為止, 較小者即為所求中位數

int M_search(SeqList &L1, SeqList &L2)
{
    int s1=0, d1=L1.length-1, m1, s2=0, d2=L2.length-1, m2;
    while(s1!=d1 || s2!=d2)
    {
        m1 = (s1+d1)/2;
        m2 = (s2+d2)/2;
        if(L1.data[m1] == L2.data[m2])
            return L1.data[m1];
        else if(L1.data[m1] > L2.data[m2])
        {
            if((s1+d1)%2 == 0)
            {
                d1 = m1;
                s2 = m2;
            }
            else
            {
                d1 = m1;
                s2 = m2+1;
            }
        }
        else
        {
            if((s1+d1)%2 == 0)
            {
                s1 = m1;
                d2 = m2;
            }
            else
            {
                s1 = m1 + 1;
                d2 = m2;
            }
        }
    }
    return L1.data[s1]>L2.data[s2]? L2.data[s2]:L1.data[s1];
}

///12.已知一個整數序列,若存在m個相同元素(m>n/2),則稱m為A中的主元素,若存在主元素,輸出,不存在,輸出-1
///王道推薦演算法(本人首先想到雜湊演算法)
///查找出現次數最多的元素為難點

int Majority(SeqList &L)///查詢可疑出現次數最多元素演算法???
{
    int c=L.data[0], num =1;
    for(int i=1;i<L.length;++i)
    {
        if(L.data[i] == c)
            num++;
        else if(num > 0)
            num--;
        else
        {
            c = L.data[i];
            num = 1;
        }
    }
    num = 0;
    for(int i=0;i<L.length;++i)
        if(c == L.data[i])
            num++;
    if(num > L.length/2)
        return c;
    else
        return -1;
}

int main()
{
    ios::sync_with_stdio(false);
    SeqList L;
    int n;
    cin>>n;
    initList(L, n);
    /*
    initList(L1, n);
    cin>>m;
    initList(L2, m);
    ListInsert(L, 5, 8);
    PrintList(L);
    cout<<"The List Length is "<<Length(L)<<endl;
    int e;
    ListDelete(L, 5, e);
    PrintList(L);
    cout<<"e's value is "<<e<<endl;
    cout<<"The List Length is "<<Length(L)<<endl;
    int order = LocateElem(L, 6);
    if(order != 0)
        cout<<"The element's order is "<<order<<endl;
    else
        cout<<"sorry, we can't find the value's order!!!"<<endl;
    DeleteMinList(L, e);
    PrintList(L);
    cout<<"e's value is "<<e<<endl;
    ReverseList(L);
    PrintList(L);
    Delete_s_among_t2(L, 6, 9);
    PrintList(L);
    L3 = combine_List(L1, L2, L3);
    PrintList(L3);
    cout<<L3.length<<endl;
    //reverse_list(L3, 2);
    Exchange(L3, 2);
    PrintList(L3);
    mid_find(L, 0, L.length-1, 5);
    PrintList(L);
    cout<<M_search(L1, L2)<<endl;*/
    cout<<Majority(L)<<endl;
    return 0;
}