常用算法整理

1、 对以下一组数据进行降序排序(冒泡排序)。
#pragma mark- 1:冒泡排序
- (void)Algorithm0 {
    int array[10] = {45, 3, 56, 13, 9, 23, 88, 17, 5, 77};
    int num = sizeof(array)/sizeof(int);
    for(int i = 0; i < num-1; i++) {
        for(int j = 0; j < num - 1 - i; j++) {
            if(array[j] < array[j+1]) {
                int tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;
            }
        }
    }
    printf("冒泡排序:");
    for(int i = 0; i < num; i++) {
        printf("%d", array[i]);
        if(i == num-1) {
            printf("\n");
        } else {
            printf(" ");
        }
    }
}

//测试结果:

2、 对以下一组数据进行升序排序(选择排序)。

#pragma mark- 2:升序排序(选择排序)
- (void)Algorithm1 {
    int numArr[10] = {45, 3, 56, 13, 9, 23, 88, 17, 5, 77};
    sort(numArr, 10);
    for (int i = 0; i < 10; i++) {
        printf("%d, ", numArr[i]);
    }
    printf("\n");
}

void sort(int a[],int n) {
    int i, j, index;
    for(i = 0; i < n - 1; i++) {
        index = i;
        for(j = i + 1; j < n; j++) {
            if(a[index] > a[j]) {
                index = j;
            }
        }
        
        if(index != i) {
            int temp = a[i];
            a[i] = a[index];
            a[index] = temp;
        }
    }
}

//测试结果: 

3、 快速排序算法


#pragma mark- 3:快速排序算法
- (void)Algorithm2 {
    int numArr[10] = {45, 3, 56, 13, 9, 23, 88, 17, 5, 77};
    sort2(numArr, 0, 9);
    printf("快速排序算法:");
    for (int i = 0; i < 10; i++) {
        printf("%d, ", numArr[i]);
    }
    printf("\n");
}

//*a 数组 indexMin:开始位置 indexMax:结束位置
void sort2(int *a, int indexMin, int indexMax) {
    if(indexMin >= indexMax) {
        return ;
    }
    
    int i = indexMin;
    int j = indexMax;
    int key = a[indexMin];
    while (i < j) {
        while (i < j && key >= a[j]) {
            j--;
        }
        a[i] = a[j];
        while (i < j && key <= a[i]) {
            i++;
        }
        a[j] = a[i];
    }
    a[i] = key;
    sort2(a, indexMin, i-1);
    sort2(a, i+1, indexMax);
}

//打印结果:快速排序算法:

4、 归并排序

#pragma mark- 4:并归排序
- (void)Algorithm3 {
    int numArr[10] = {45, 3, 56, 13, 9, 23, 88, 17, 5, 77};
    int tempArr[10];
    sort(numArr, tempArr, 0, 9);
    printf("并归排序:");
    for (int i = 0; i < 10; i++) {
        printf("%d, ", numArr[i]);
    }
    printf("\n");
}

void merge(int sourceArr[], int tempArr[], int startIndex, int midIndex, int endIndex) {
    
    int i = startIndex;
    int j = midIndex + 1;
    int k = startIndex;
    while (i != midIndex + 1 && j != endIndex + 1) {
        if (sourceArr[i] >= sourceArr[j]) {
            tempArr[k++] = sourceArr[j++];
        } else {
            tempArr[k++] = sourceArr[i++];
        }
    }
    
    while (i != midIndex + 1) {
        tempArr[k++] = sourceArr[i++];
    }
    
    while (j != endIndex + 1) {
        tempArr[k++] = sourceArr[j++];
    }
    
    for (i = startIndex; i <= endIndex; i++) {
        sourceArr[i] = tempArr[i];
    }
}


void sort(int souceArr[], int tempArr[], int startIndex, int endIndex) {
    
    int midIndex;
    if (startIndex < endIndex) {
        midIndex = (startIndex + endIndex) / 2;
        sort(souceArr, tempArr, startIndex, midIndex);
        sort(souceArr, tempArr, midIndex + 1, endIndex);
        merge(souceArr, tempArr, startIndex, midIndex, endIndex);
    }
}

5、 二分查找算法

#pragma mark- 5:二分查找算法
- (void)Algorithm4 {
    //给定一个排序数组
    int numArr[10] = {3, 5, 9, 13, 17, 23, 45, 56, 77, 88};
    //从数组中找到目标23
    int targetIndex = bsearchWithoutRecursion(numArr, 0, 9, 23);
    printf("二分查找算法:");
    if (targetIndex >= 0) {
        printf("找到目标位置%d, ", targetIndex);
    } else {
        printf("未找到目标!");
    }
    printf("\n");
    
}

int bsearchWithoutRecursion(int array[],int low,int high,int target) {
    
    while(low <= high) {
        int mid = (low + high) / 2;
        if(array[mid] > target) {
            high = mid - 1;
        } else if(array[mid] < target) {
            low = mid + 1;
        } else {//找到
            return mid;
        }
    }
    //找不到
    return -1;
}

6、递归实现

#pragma mark- 6:递归实现 查找算法
- (void)Algorithm5 {
    //给定一个排序数组
    int numArr[10] = {3, 5, 9, 13, 17, 23, 45, 56, 77, 88};
    //从数组中找到目标23
    int targetIndex = binarySearch(numArr, 0, 9, 23);
    printf("递归实现查找算法:");
    if (targetIndex >= 0) {
        printf("找到目标位置%d, ", targetIndex);
    } else {
        printf("未找到目标!");
    }
    printf("\n");
    
}

int binarySearch(const int arr[],int low,int high,int key) {
    int mid=low + (high - low) / 2;
    if(low > high)
        return -1;
    else{
        if(arr[mid] == key)
            return mid;
        else if(arr[mid] > key)
            return binarySearch(arr, low, mid-1, key);
        else
            return binarySearch(arr, mid+1, high, key);
    }
}

6、 如何实现单链表翻转(链表逆序)

#pragma mark- 7:链表翻转(单链表逆序)
- (void)Algorithm6 {
    /*
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 
相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,
比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,
而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。
比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。
最容易想到的方法遍历一遍链表,利用一个辅助指针,
存储遍历过程中当前指针指向的下一个元素,
然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。
     */
    node *head = createLinkList(7);
    
    if (head) {
        printLinkList(head);
        node *reHead = reverseFunc1(head);
        printLinkList(reHead);
        free(reHead);
    }
    
    free(head);
}

node *createLinkList(int length) {
    if (length <= 0) {
        return NULL;
    }
    
    node *head,*p,*q;
    int number = 1;
    head = (node *)malloc(sizeof(node));
    head->num = 1;
    head->next = head;
    p = q = head;
    
    while (++number <= length) {
        p = (node *)malloc(sizeof(node));
        p->num = number;
        p->next = NULL;
        q->next = p;
        q = p;
    }
    
    return head;
}


void printLinkList(node *head) {
    if (head == NULL) {
        return;
    }
    node *p = head;
    while (p) {
        printf("%d ", p->num);
        p = p -> next;
    }
    printf("\n");
}

node *reverseFunc1(node *head) {
    if (head == NULL) {
        return head;
    }
    node *p,*q;
    p = head;
    q = NULL;
    while (p) {
        node *pNext = p -> next;
        p -> next = q;
        q = p;
        p = pNext;
    }
    return q;
}

7、 实现一个字符串“how are you”的逆序输出(编程语言不限)。如给定字符串为“hello world”,输出结果应当为“world hello”。

// 对指针p和q之间的所有字符逆序
void ReverseWord(char* p, char* q)
{
    while(p < q)
    {
        char t = *p ;
        *p++ = *q ;
        *q-- = t ;
    }
}

// 将句子按单词逆序
char* ReverseSentence(char* s)
{
    // 这两个指针用来确定一个单词的首尾边界
    char* p = s ; // 指向单词的首字符
    char* q = s ; // 指向空格或者 '\0'
    
    while(*q != '\0')
    {
        if (*q == ' ')
        {
            ReverseWord(p, q - 1) ;
            q++ ; // 指向下一个单词首字符
            p = q ;
        }
        else
            q++ ;
    }
    
    ReverseWord(p, q - 1) ; // 对最后一个单词逆序
    ReverseWord(s, q - 1) ; // 对整个句子逆序
    printf("%s", s);
    return s ;
}

8、 给定一个字符串,输出本字符串中只出现一次并且最靠前的那个字符的位置?如“abaccddeeef”,字符是b,输出应该是2。

9、 二叉树

二叉树
二叉树的遍历大概分为四种: 分别是前序遍历,中序遍历,后序遍历,按层遍历
(1) 前序遍历:根节点------左子树------右子树

结果: A -> ( B -> C -> D ) -> E -> F -> G
(左子树里面循环套用前序遍历法,结果是 B -> C -> D, 其它同理)

(2) 中序遍历:左子树---根节点--右子树

结果: ( C -> B -> D ) -> A -> E -> F -> G

(3) 后序遍历:左子树---右子树---根节点

结果: ( C -> D -> B ) -> G ->F -> E -> A

(4) 按层遍历: 上到下,左到右顺序

结果: A -> B -> E ->C -> D ->F -> G

10、 打印2-100之间的素数。
#pragma mark- 9:求2-100间的 素数
- (void)Algorithm8 {
    for (int i = 2; i < 100; i++) {
        int r = isPrime(i);
        if (r == 1) {
            printf("%d ", i);
        }
    }
}
/*
 所谓素数是指除了1和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被2~16的任一整数整除。因此判断一个整数m是否是素数,只需把m被2~m-1之间的每一个整数去除,如果都不能被整除,那么m就是一个素数
 另外判断方法还可以简化。m不必呗2~m-1之间的每一个整数去除,只需被2~√m之间的每一个整数去除就可以了。如果m不能被2~√m间任一整数整除,m必定是素数。例如判别17是是否为素数,只需使17被2~4之间的每一个整数去除,由于都不能整除,可以判定17是素数。(原因:因为如果m能被2~m-1之间任一整数整除,其二个因子必定有一个小于或等于√m,另一个大于或等于√m。例如16能被2,4,8整除,16=2*8,2小于4,8大于4,16=4*4,4=√16,因此只需判定在2~4之间有无因子即可)
 */
int isPrime(int n) {
    int i;
    for(i = 2; i <= sqrt(n); i++) {
        if(n % i == 0) {
            return 0;
        }
    }
    return 1;
}

11、 求两个整数的最大公约数

#pragma mark- 10:最大公因(约)数 (辗转相除法)
- (void)Algorithm9 {
    printf("最大公因数:%d ", maxGcd(18,6));
}
/*
 最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。
 求最大公约数算法:
 (1)辗转相除法
 有两整数a和b:
 ① a%b得余数c
 ② 若c=0,则b即为两数的最大公约数
 ③ 若c≠0,则a=b,b=c,再回去执行①
 例如求27和15的最大公约数过程为:
 27÷15 余12 ,15÷12余3 ,12÷3余0因此,3即为最大公约数
 
 ⑵ 相减法
 有两整数a和b:
 ① 若a>b,则a=a-b
 ② 若a12 ) 15-12=3( 12>3 )
 12-3=9( 9>3 ) 9-3=6( 6>3 )
 6-3=3( 3==3 )
 因此,3即为最大公约数
 */
int maxGcd(int a, int b) {
    int temp = 0;
    if (a < b) {
        temp = a;
        a = b;
        b = temp;
    }
    while (b != 0) {
        temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

12、 最小公倍数

/*
 求最小公倍数算法:
 
 最小公倍数 = 两整数的乘积 ÷ 最大公约数
 */
#pragma mark- 11:最小公倍数
- (void)Algorithm10 {
    int A = 18,B = 6;
    printf("最小公倍数:%d ", A * B / maxGcd(A,B));
}

13、 题:求一个矩阵中最大的n==2的二维子矩阵(元素和最大).如:

      1 2 0 3 4
      2 3 4 5 1
      1 1 5 3 0
      中最大的是:  
      4 5
      5 3
      要求:(1)写出算法;(2)分析时间复杂度;(3)用C写出关键代码

分析:方法一、这是最容易想到也是最容易实现的方法。遍历矩阵(行迭代器为i,列迭代器为j),以当前遍历到的元素为首a[i,j],计算二维子矩阵的和(sum=a[i,j]+a[i+1,j]+a[i,j+1]+a[i+1,j+1]),并找出和最大的二维矩阵,注意矩阵的最后一行和最后一列不用遍历。时间复杂度为O(i*j)。

实现代码:

 void get_max_22Matrix(int *a,int row,int col,int *result)  
//a为原矩阵,row,col指a矩阵的行和列,result存储最终得到的子二维矩阵  
{  
  int maxsum=0,result_i,result_j,sum;  
    
#define a(i,j) *(a+(i)*col+(j))  //用二维的形式表示一维数组,访问需要一定的代价  
#define result(i,j) *(result+(i)*2+(j))  
    
  for(int i=0; i

14、输入n个整数,输出其中最小的k个

/思路:把输入的n个整数排序,排在最前面的k个数就是最小的k个数。时间复杂度为O(nlogn)/

#include   
#include   
#include   
using namespace std;  
 
//bool cmp(int &a, int &b)  
//{  
//  return a < b;  
//}  
int main()  
{  
    int n,k;  
    cin >> n;  
    cin >> k;  
    vector  array;  
    for (int i = 0; i < n;i++)  
    {  
        int m;  
        cin >> m;  
        array.push_back(m);  
    }  
    sort(array.begin(),array.end());//sort默认就是升序(从小到大),不用重载cmp  
    for (int i = 0; i < k;i++)  
    {  
        cout << array[i];  
        if (i == k - 1) //注意最后一个数输出后不能有空格  
        {  
            cout << endl;  
            continue;  
        }  
        cout << ' ';    
    }  
    return 0;  
}

参考:
1: http://blog.csdn.net/yangshebing21/article/details/51292477
2: http://www.jianshu.com/nb/2488809
3:

你可能感兴趣的:(常用算法整理)