[筆試]常考算法

#include<iostream>
using namespace std;
#include<cmath>
#include<iomanip>

//虛函數
/*class ClassA
{
public:
    ClassA()
    {
        cout<<"A類構造函數被調用"<<endl;
    
    }
    ~ClassA()
    {
        cout<<"A類析構函數被調用"<<endl;
    
    }
    virtual void getnum()=0;
    //{
    //    cout<<"A類虛函數被調用"<<endl;

        
    //}
        
private:
        int num;
        char *str;
        double dnum;
};


class ClassB:public ClassA
{
public:
    ClassB()
    {
        cout<<"B類構造函數被調用"<<endl;
    
    }
    ~ClassB()
    {
        cout<<"B類析構函數被調用"<<endl;
    
    }
    virtual void getnum()
    {
        cout<<"B類虛函數被調用"<<endl;
        
    
    }
private:
    char Bstr[10];


};

void  main()
{
    ClassA *pc;
    ClassB B;
    pc=&B;
    pc->getnum();
    getchar();

}*/

/*
上一程序的縮略版
class ClassA
{
public:
    virtual void getnum()
    {
        cout<<"A類虛函數被調用"<<endl;
    }    
};
class ClassB:public ClassA
{
public:
    virtual void getnum()
    {
        cout<<"B類虛函數被調用"<<endl;
    }
};
void  main()
{   ClassA *pc;
    ClassB B;
    pc=&B;
    pc->getnum();
    getchar();
}*/



/*
經過鍵盤輸入一串小寫字母(a~z)組成的字符串。請編寫一個字符串過濾程序,若字符串中出現多個相同的字符,
將非首次出現的字符過濾掉。
好比字符串「abacacde」過濾結果爲「abcde」。
*/

void stringFilter(const char *pInputStr, long lInputLen, char *pOutputStr)
{
    //const char *TempStr=pInputStr;
    int count1=0;
    int count2=0;
    int i=0;
    while(count1<=lInputLen)
    {
        for(i=0;i<=count2;)
        {
            if(*(pInputStr+count1)!=*(pOutputStr+i))//判斷是否有重複字符
                 i++;
            else 
                break;
        }
        if(i>count2)
        {
            *(pOutputStr+count2)=*(pInputStr+count1);
            count2++;
        }
           
        count1++;
    
    }


}




/*經過鍵盤輸入一串小寫字母(a~z)組成的字符串。請編寫一個字符串壓縮程序,將字符串中連續出席的重複字母進行壓縮,
並輸出壓縮後的字符串。
壓縮規則:
1. 僅壓縮連續重複出現的字符。好比字符串"abcbc"因爲無連續重複字符,壓縮後的字符串仍是"abcbc".
2. 壓縮字段的格式爲"字符重複的次數+字符"。例如:字符串"xxxyyyyyyz"壓縮後就成爲"3x6yz"*/

void stringZip(const char *pInputStr, long lInputLen, char *pOutputStr)
{
    int i=0;
    int j=0;
    int k=0;
        for(i=0;i<lInputLen;i=j)
        {
            for(j=i+1;j<lInputLen;j++)
                if(*(pInputStr+j)!=*(pInputStr+i))
                    break;
            if(j!=i+1)
                *(pOutputStr+k++)=char(j-i+'0');
            
           *(pOutputStr+k++)=*(pInputStr+i);
        }
      




}
/* 
題目描述(50分): 
經過鍵盤輸入100之內正整數的加、減運算式,請編寫一個程序輸出運算結果字符串。 
輸入字符串的格式爲:「操做數1 運算符 操做數2」,「操做數」與「運算符」之間以一個空格隔開。 
 
補充說明: 
1. 操做數爲正整數,不須要考慮計算結果溢出的狀況。 
2. 若輸入算式格式錯誤,輸出結果爲「0」。 
 
要求實現函數: 
void arithmetic(const char *pInputStr, long lInputLen, char *pOutputStr); 
 
【輸入】 pInputStr:  輸入字符串 
         lInputLen:  輸入字符串長度 
【輸出】 pOutputStr: 輸出字符串,空間已經開闢好,與輸入字符串等長; 
 
【注意】只須要完成該函數功能算法,中間不須要有任何IO的輸入輸出 
 
示例 
輸入:「4 + 7」  輸出:「11」 
輸入:「4 - 7」  輸出:「-3」 
輸入:「9 ++ 7」  輸出:「0」 注:格式錯誤 
*/  
bool Isnumber(char c)
{
    if(c<='9'&&c>='0'){  
        return true;  
    }else{  
        return false;  
    }  

}
void arithmetic(const char *pInputStr, long lInputLen, char *pOutputStr)
{

    int ops1=0;
    int ops2=0;
    int num=0;
    char Coptr;
    int i=0;
    int j=0;
    int isvailed=0;
    while(Isnumber(pInputStr[i]))
    {
        ops1=ops1*10+(int)(pInputStr[i]-'0');
        i++;
    }
    //cout<<ops1<<endl;
    if(i==0)
        isvailed=1;
    while(pInputStr[i++]==' ');
    //cout<<i<<endl;
    j=i-1;
    Coptr=pInputStr[j];//獲取操做符
    //cout<<Coptr<<endl;
    while(pInputStr[j++]==' ');
    j=i+1;
    while(Isnumber(pInputStr[j]))
    {
        ops2=ops2*10+(int)(pInputStr[j]-'0');
        j++;
    }

    if(j==(i+1))
        isvailed=1;
    
    
    
    if(isvailed==1)
        *pOutputStr='0';
    else
    {
        switch(Coptr)
       {
        case '+':
           num=ops1+ops2;
           break;
        case '-':
           num=ops1-ops2;
           break;
         case '*':
           num=ops1*ops2;
           break;
        case '/':
            num=ops1/ops2;
            break;
        default:
            *pOutputStr='0';
            break;
        }
     }
    if(num==0)
        *pOutputStr='0';
    
    int scale=100;
    if(num<0)
    {
        *pOutputStr++='-';
        num=-num;
    }
    
    for(int k=0;k<3;k++)
    {
        if(num/scale)
        {
            *pOutputStr++=char(num/scale+'0');
            
        }
        num=num%scale;
        if(num==0)
        {
            *pOutputStr++=char('0');
            break;
        }
        scale/=10;
    
    }
    

}
/*1 字串轉換
問題描述:
將輸入的字符串(字符串僅包含小寫字母‘a’到‘z’),按照以下規則,循環轉換後輸出:a->b,b->c,…,y->z,z->a;
若輸入的字符串連續出現兩個字母相同時,後一個字母須要連續轉換2次。例如:aa 轉換爲 bc,zz 轉換爲 ab;
當連續相同字母超過兩個時,第三個出現的字母按第一次出現算。
要求實現函數:
void convert(char *input,char* output)
【輸入】  char *input , 輸入的字符串
【輸出】  char *output ,輸出的字符串
【返回】 無
示例
輸入:char*input="abcd" 
輸出:char*output="bcde"
輸入:char*input="abbbcd" 
輸出:char*output="bcdcde"   3*/
void convert(char *input,char* output)
{
    int i=0;
    int j=0;
    int k=0;
    int temp=1;
    while(input[j++]!='\0')
    {        
        
        if(input[i-1]!=input[i])
            output[k++]=input[i++]+1;
        else
        {
            temp++;
            if(temp==3)
                output[k++]=input[i++]+1;
            else
                output[k++]=input[i++]+2;    
            
                
        }
    }
}  
/*2 字符串處理轉換
問題描述:    
在給定字符串中找出單詞( 「單詞」由大寫字母和小寫字母字符構成,其餘非字母字符視爲單詞的間隔,
如空格、問號、數字等等;另外單個字母不算單詞);找到單詞後,按照長度進行降序排序,
(排序時若是長度相同,則按出現的順序進行排列),而後輸出到一個新的字符串中;
若是某個單詞重複出現屢次,則只輸出一次;若是整個輸入的字符串中沒有找到單詞,請輸出空串。
輸出的單詞之間使用一個「空格」隔開,最後一個單詞後不加空格。
要求實現函數:
void my_word(charinput[], char output[])
【輸入】  char input[], 輸入的字符串
【輸出】  char output[],輸出的字符串
【返回】 無
示例
輸入:charinput[]="some local buses, some1234123drivers" ,
輸出:charoutput[]="drivers local buses some"
輸入:charinput[]="%A^123 t 3453i*()" ,
輸出:charoutput[]=""*/

void my_word(char input[], char output[])
{
    int i=0;
    int j=0;
    int len=0;
    int k=0;
    int s=0;
    int m=0;
    while(input[len++]!='\0');
    cout<<len<<endl;
    char *tstr=new char[len];
    while(input[j]!='\0')
    {
        s=0;
        for(i=j;i<len-1;)
        {
            if((input[i]>='a'&&input[i]<='z')||(input[i]>='A'&&input[i]<='Z'))    
            {
                tstr[s++]=input[i++];
            }
            else
            {
                i++;
                break;
            }
        }
         if (s>1)
            {
              for(k=0;k<s;k++)
                  output[m++]=tstr[k];
              output[m++]=' ';
             }
            j=i;
    }


    //cout<<j<<endl;
    delete [] tstr;


}


/*【功能】:判斷給定的一個數iNumber是不是一個素數
【輸入】:一個整型數 iNumber
【輸出】:0:不是素數
                   1:是素數
*/
int isPrimNumber(int iNumber)
{
         if(iNumber == 1)
               return 0;
         if(iNumber == 2)
               return 1;
         for(int i = 2; i <= sqrt((double)iNumber); ++ i)

         {
                 if(iNumber % i == 0)
                          return 0;
          }
          return 1;
   }

/* 
【功能】:找出一個數組iArray[]中大於等於平均值的元素個數
【輸入】:數組iArray, 數組的元素個數nSize
【輸出】:大於等於平均值的元素個數cnt
*/
int func(int iArray[],int nSize)
{
    int i=0;
    int num=0;
    double Array=0;
    int cnt=0;
    for(i=0;i<nSize;i++)
        num+=iArray[i];
     Array=num*1.0/nSize;
     for(i=0;i<nSize;i++)
         if(iArray[i]>=Array)
             cnt++;
     return cnt;
}

/* 
【功能】:判斷一個數是否迴文數,若是1221,232, 3;
【輸入】:一個整型數iNumber
【輸出】:0: iNumber不是迴文數
          1:iNumber是迴文數
*/
int isPlalindromeNumber(int iNumber)
{
    int src = iNumber;
         int des = 0;

         while(src)
         {
                des = des * 10 + src % 10;
                src /= 10;
          }

         if(des != iNumber)
                 return 0;
          return 1;



}



 /* 
【功能】:求解出特定數iNumber以內的全部素數,將這些素數存入一個數組primNumber[]中
【輸入】:特定的數iNumber
*/
 void getPrim(int iNumber) 
 {
     int primNumber[100]={2,3,5};
     int trial=5;
     int count=3;
    
    do
    {
        int found=0;
        trial+=2;
        for(int i=0;i<count;i++)
        {
            found=(trial%(primNumber[i]))==0;
            if(found)
                break;

        }
        if(!found)
        primNumber[count++]=trial;
    
    
    }while(trial<iNumber);
    int n=0;
    for(int i=0;i<count;i++)
    {
        cout<<setw(10)<<*(primNumber+i);
        n++;
        if(n==5)
        {
            n=0;
            cout<<endl;
        
        }
        
    
    
    }
 
 
 }
 int func(int x) 
{ 
int countx =0; 
while(x) 
{ 
countx ++; 
x = x&(x-1); 
} 
return countx; 
}

 /***********************************三種簡單排序方法**************************************************
 直接插入排序   穩定
 冒泡排序       穩定
 直接選擇排序   不穩定
 時間複雜度均爲O(n方) 空間複雜度O(1)
 穩定算法:兩個相等的關鍵字若排序先後位置不變則穩定



 
 直接插入排序,也是分紅兩個序列,待排序列和已排好序列,每次從待排序列裏去一個數,將其插入到已排好序列中
 顯然,只要最後的一個數每排好,全部已排好序列數的位置都有可能會變更。
 先把當前待拍元素保存起來,用j來循環已排好序列,找到插入位置,這個尋找過程就是不斷移動元素的過程
 input[j + 1] = input[j]; 
 input[j] = temp;



 直接插入排序適合原始數據基本有序且長度較小的狀況下
 */
 void InsertionSort(int input[],int len) 
{
     int i,j,temp;
     for (i = 1; i < len; i++) 
     {
          temp = input[i];  /* 操做當前元素,先保存在其它變量中 */
          for (j = i - 1;j>-1&&input[j] > temp ; j--) /* 從當前元素的上一個元素開始查找合適的位置 */
          {
               input[j + 1] = input[j]; /* 一邊找一邊移動元素 */
               input[j] = temp;
          }
     }
}



/*直接選擇算法的思想是將數列分紅兩部分,一部分是待排序列,一部分是已經拍好的序列
顯然,一開始已經排好的序列只有第一個元素,每次從待排序列裏選一個最小的跟已經排好的序列最大的交換
對於已排好序列是不會發生改變的除了最後一個元素。
直接選擇算法時間複雜度爲O(n方),空間複雜度O(1)。他是一個不穩定的算法
*/
void SelectSort(int input[],int len)
{
    int i=0;//第一層循環,i永遠表示已排好序列的最後一個元素
    int j=0;//第二層循環,j永遠表示待排序列的第一個元素
    int temp=0;//中間變量
    for(i=0;i<len;i++)
        for(j=i+1;j<len;j++)
            if(input[i]>input[j])
            {
                temp=input[j];
                input[j]=input[i];
                input[i]=temp;
            }
}

/*
冒泡排序
每輪沉澱一個最大的數到最後,在最好的狀況下冒泡排序和直接插入排序是最快的。



*/
void BubleSort(int input[],int len)
{

    int i=0;//第一層循環
    int j=0;//第二層循環
    int temp=0;//中間變量
    for(int i=0;i<len;i++)
    {    for(int j=0;j<len-i-1;j++)
        {
            if(input[j]>input[j+1])
            {
                temp=input[j];
                input[j]=input[j+1];
                input[j+1]=temp;
            }
        }
    }
}



/*快速排序
快速排序適合原始數據雜亂無章,n較大且對穩定性沒有要求的狀況,平均狀況下,快速排序最快,時間複雜度
O(nlogn),空間複雜度爲O(logn)

*/
int partition(int input[],int low,int high)
{
    
    int pivotey=input[low];
    low=low+1;
    while(low<high)
    {
        while(low<high&&input[high>=pivotey])--high;
            input[low]=input[high];
        while(low<high&&input[low]<=pivotey)++low;
            input[high]=input[low];
    }
    input[low]=pivotey;
    return low;
}
void Qsort(int input[],int low,int high)
{
    int pivoloc=0;
    if(low<high)
    {
        pivoloc=partition(input,low,high);
        Qsort(input,low,pivoloc-1);
        Qsort(input,pivoloc+1,high);
    
    }



}







//編程實現字符串到整數的轉換函數
int parseInt(char *str,int radix)
{
    int i=0;
    int j=0;

    //首先判斷他是否是一個合法的整數
    int len=strlen(str);
    while(i<len)
      if((*(str+i)>=48)&&(*(str+i)<=57)||(*(str+i)>=65)&&(*(str+i)<=90)||(*(str+i)>=97)&&(*(str+i)<=122))
          i++;
      else
           break;
    try
    {
         if(i<len||len==0)
         throw "整數不合法";
    
    }
    catch(const char aMessage())
    {
        cout<<endl<<aMessage<<endl;
        

    }
    //字符轉換
    int temp=0;
    int num=0;
    j=len;
    int k=0;
    cout<<str<<endl;
    while(j>=0)
    {
        if((*(str+k)>=65)&&(*(str+k)<=90))
            temp=*(str+k)-54;
        if((*(str+k)>=97)&&(*(str+k)<=122))
            temp=*(str+k)-86;
        if((*(str+k)>=48)&&(*(str+k)<=57))
            temp=*(str+k)-48;

        num+=(int)temp*pow((double)radix,(int)j-1);
        j--;
        k++;
    }
    try
    {
         if(!(num>=-32768||num<=32767))
         throw "整數越界";
    
    }
    catch(const char aMessage())
    {
        cout<<endl<<aMessage<<endl;

    }             




   return num;


}


//籠子裏有雞和兔子,共100條腿,問雞有多少,兔子有多少,有多少可能性
int lag(int num)
{
    int chken=0;
    int rubb=0;
    int k=0;
    int snum=0;
    while(chken<=(num/2))
    {

        k=(num-chken*2)%4;
        rubb=(num-chken*2)/4;
        if(k==0)
        {
            cout<<"雞的數目爲"<<chken<<" "<<" 鴨的數目爲"<<rubb<<endl;
            snum++;
        }
            
            chken++;
    }
    cout<<"總可能性爲"<<snum<<endl;
    return 1;

}




//********單鏈表的的問題***********************

//定義一個鏈表節點
//單向鏈表節點
struct node
{
    int data;
    node *next;

}Node;
//雙向鏈表節點
struct dnode
{
    int data;
    dnode *left;
    dnode *right;

}Dnode;
//建立並初始化單鏈表
struct node * Initlist(int n)
{
    node *head;
    head=(node*)malloc(sizeof(node));
    head->next=NULL;
    head->data=0;
    node *p=head;
    int data=0;
    int i=0;
    while(i<n)
    {
       node *L;
       L=(node*)malloc(sizeof(node));
       cin>>data;
       p->next=L;
       L->data=data;
       p=L;
       i++;
    }
    p->next=NULL;
    return head;


}

//單鏈表輸出
void puts(struct node *head)
{
    node * p=NULL;
    for(p=head->next;p!=NULL;p=p->next)
        cout<<p->data<<" ";
    cout<<endl;

}

//單鏈表就地逆置
//思路很簡單就是 用三個變量,P用來循環節點,r用來控制最後一個節點被鏈接上,q是最重要的中間節點。
void Reverselist(struct node *head)
{
    node *p=head->next;
    node *q=NULL;
    node *r=NULL;
    while(p)
    {
        r=q;
        q=p;
        p=p->next;
        q->next=r;
    
    
    }
    head->next=q;
}


//帶尾指針的循環單鏈表,有不少好處,其中之一就是找最後一個元素的時候不須要遍歷整個鏈表,但凡涉及到不須要遍歷的
//儘可能考慮尾指針單鏈表的狀況。

//兩個鏈表A,B有序,合併成一個依然有序的單鏈表C,注意不要增長空間複雜度

int mubble(node *ListA,node *ListB)
{
    node *p=NULL;
    p=ListA->next;
    node *q=NULL;
    q=ListB->next;
    node *c=NULL;

    while(p->next!=NULL&&q!=NULL)
    {
        while(p->data<=q->data&p!=NULL)
        {
            c=p;
            if(p->next!=NULL)
              p=p->next;
        }
        c->next=q;    
        while(q->data<=p->data&&q!=NULL)
        {
            c=q;
            if(q->next!=NULL)
            q=q->next;
        }
        c->next=p;
    }
    c->next=q;
    return 1;
}


//編寫string類的構造函數、析構函數、賦值
class String
{
public:
    String(const char *str=NULL);
    String(const String &other);
    ~String();
    String & operator =( const String &other);
    
private:
    char *data;

};

String::String(const String &other)
{
    int len=strlen(other.data);
    data=new char(len+1);
    strcpy(data,other.data);
}

String::~String()
{
    delete [] data;

}

String & String::operator =( const String &other)
{
     if(this == &other)
        return *this;
    delete [] data;
    int length = strlen(other.data);  
    data = new char[length+1];
    strcpy(data, other.data);
    return *this;
}


void main()
{
//    char instr[]="ppddsdpp";
//    char neinstr[]="5 - 15";
//    int n=sizeof(instr);
    //char outstr[100]={ };
    //char aa[]="hello";
    //char cstr[]="a3c3hello212my221dd22www";
    //stringFilter(instr,n,outstr);
    //stringZip(instr,n,outstr);
    //arithmetic(neinstr,n,outstr);
    //cout<<aa<<endl;
    //cout<<outstr<<endl;
    //cout<<noutstr<<endl;
    //convert(cstr,outstr);
    //my_word(cstr,outstr);
    //cout<<outstr<<endl;
    /*int a=121;
    bool f=isPrimNumber(a);
    if(f)
        cout<<"這是一個素數"<<endl;
    else
        cout<<"這不是一個素數"<<endl;*/

    
    
    /*int ary[6]={4,4,21,1,2,23};
    int k=func(ary,6);
    cout<<k;*/

    /*int i=12344221;
    bool f=isPlalindromeNumber(i);
    if(f)
        cout<<"這是一個迴文"<<endl;
    else
        cout<<"這不是一個迴文"<<endl;
    getPrim(100); */

    //int a=230;
    //cout<<func(a)<<endl;
    //int a[10]={2,34,5,22,212,32,43,12,9,12};
    //InsertionSort(a,10);
    //SelectSort(a,10);
    //BubleSort(a,10);
    //Qsort(a,0,9);
    //for(int i=0;i<10;i++)
    //    cout<<a[i]<<" ";
    /*int b=5;
    int  * const p=&b;
    int a=12;
    int  * const r=&b;
    const int * p=&a;
    int k=6;
    //p=&k;
    b=k;
    cout<<b<<endl;*/
    //char *ss="hello";
    //int p=sizeof(ss);
    //int q=strlen(ss);
    //cout<<p<<q;
    //int a=0;
    //char b='a';
    


    //char str[]="1000";
    //int k=parseInt(str,2);
    //cout<<k;
    
    //lag(100);
    struct node * L1=Initlist(5);
    struct node * L2=Initlist(7);
    puts(L1);
    puts(L2);
    mubble(L1,L2);
    //Reverselist(L1);
    puts(L1);
    system("pause");

}
相關文章
相關標籤/搜索