算法

排序:排序
链表:iOS单向链表数据结构、判断两个链表是否相交并找出交点
求解1-100之间的所有素数/质数:https://zhidao.baidu.com/question/1430132761736407379.html

字符串反转

  • 要求:
    给定字符串“hello,word”,实现将其反转。
    输出结果:"drow,olleh"

-思路:
begin指针指向第一个字符;
end指针指向最后一个字符;
交换两个指针的内容,begin指针向后移动一位、end指针向前移动一位,交互下一对;

void char_reverse(char* cha)
{
    // 指向第一个字符
    char* begin = cha;
    // 指向最后一个字符
    char* end = cha + strlen(cha) - 1;
    
    while (begin < end) {
        // 交换前后两个字符,同时移动指针
        char temp = *begin;
        *(begin++) = *end;
        *(end--) = temp;
        
    }
    
}

调用:

    //字符串数组
    char ch[] = "hello,world";/*char * ch = "hello,world"; 不可以*/
    char_reverse(ch);

    printf(ch);

链表反转

  • 要求:


    链表反转
  • 思路:
    1.原本的联调头结点为Head;
    2.生成一个新的头节点NewH,作为反转后链表的头结点;
    3.生成一个临时节点P,用来保存操作节点的下一个节点。例如目前要操作的节点是1,p就指向的是2;
    4.先把内容为1的节点拿出来,作为新链表的头结点。头结点NewH指向内容为1的节点。
    5.把p节点指向2的下一个节点。
    6.内容为2的节点拿出来,作为新链表的头结点。头结点NewH指向内容为2的节点。依次类推。(每一个节点都插入到新链表,作为新链表的头结点)

链表反转
链表反转
链表反转
.h:
// 定义一个节点
struct Node {
    int data;//节点数据
    struct Node *next;//链表的下一个节点
};

@interface ReverseList : NSObject
// 链表反转
struct Node* reverseList(struct Node *head);
// 构造一个链表
struct Node* constructList(void);
// 打印链表中的数据
void printList(struct Node *head);

@end

.m:
@implementation ReverseList

/*
 传入:原链表的头结点
 返回:新链表的头结点
 */
struct Node* reverseList(struct Node *head)
{
    // 定义遍历指针,初始化为头结点
    struct Node *p = head;
    // 反转后的链表头部
    struct Node *newH = NULL;
    
    // 遍历链表
    while (p != NULL) {
        
        // 记录下一个结点
        struct Node *temp = p->next;
        // 当前结点的next指向新链表头部
        p->next = newH;
        // 更改新链表头部为当前结点
        newH = p;
        // 移动p指针
        p = temp;
    }
    
    // 返回反转后的链表头结点
    return newH;
}
// 构造一个链表
struct Node* constructList(void)
{
    // 头结点定义
    struct Node *head = NULL;
    // 记录当前尾结点
    struct Node *cur = NULL;
    
    for (int i = 1; i < 5; i++) {
        struct Node *node = malloc(sizeof(struct Node));
        node->data = I;
        
        // 头结点为空,新结点即为头结点
        if (head == NULL) {
            head = node;
        }
        // 当前结点的next为新结点
        else{
            cur->next = node;
        }
        
        // 设置当前结点为新结点
        cur = node;
    }
    
    return head;
}
// 打印链表中的数据

void printList(struct Node *head)
{
    struct Node* temp = head;
    while (temp != NULL) {
        printf("node is %d \n", temp->data);
        temp = temp->next;
    }
}

@end

调用:

  // 单链表反转
    struct Node* head = constructList();
    printList(head);
    printf("---------\n");
    struct Node* newHead = reverseList(head);
    printList(newHead);

有序数组合并

  • 要求:
    如下,有两个有序数组。分别是[1,4,6,7,9]、[2、3、5、6、8、10、11、12]


    有序数组合并

1.两个数组a、b。用一个新的数组c放合并的结果。比如p存放数组a遍历到的位数,q存放b数组遍历到的位数。
2.a[p]和b[q]进行比较,假如a[p]小,就把a[p]放到数组c中,并且把p+1。反之,如果b[q]小,就把b[q]放到数组里面,q+1。
3.然后再用新的p和q进行比较。直到某一个数组变量完后,看哪个数组没有变量完,把没有变量完的部分放到数组c里面。

有序数组合并
有序数组合并
有序数组合并
@interface MergeSortedList : NSObject
// 将有序数组a和b的值合并到一个数组result当中,且仍然保持有序
void mergeList(int a[], int aLen, int b[], int bLen, int result[]);

@end

@implementation MergeSortedList

void mergeList(int a[], int aLen, int b[], int bLen, int result[])
{
    int p = 0; // 遍历数组a的指针
    int q = 0; // 遍历数组b的指针
    int i = 0; // 记录当前存储位置
    
    // 任一数组没有到达边界则进行遍历
    while (p < aLen && q < bLen) {
        // 如果a数组对应位置的值小于b数组对应位置的值
        if (a[p] <= b[q]) {
            // 存储a数组的值
            result[i] = a[p];
            // 移动a数组的遍历指针
            p++;
        }
        else{
            // 存储b数组的值
            result[i] = b[q];
            // 移动b数组的遍历指针
            q++;
        }
        // 指向合并结果的下一个存储位置
        I++;
    }
    
    // 如果a数组有剩余
    while (p < aLen) {
        // 将a数组剩余部分拼接到合并结果的后面
        result[i] = a[p++];
        I++;
    }
    
    // 如果b数组有剩余
    while (q < bLen) {
        // 将b数组剩余部分拼接到合并结果的后面
        result[i] = b[q++];
        I++;
    }
}

@end

调用:

  // 用于存储归并结果
    int result[13];
    // 归并操作g
    mergeList(a, 5, b, 8, result);
    // 打印归并结果
    printf("merge result is ");
    for (int i = 0; i < 13; i++) {
        printf("%d ", result[I]);
    }
    

Hash算法

查找一个字符串中,第一个只出现一次的字符

  • 一个字符长度是8,每一位有0、1两种组成可能,所以1个字符有2的8次方个可能,就是256个可能。

采用hash算法思想:

  • 定义一个256大小的数组,数组中存储的是每个字符出现的次数。
  • 每个字母根据ascii码值,把次数放到对应的位置。例如a的ascii值是97,数组的第97位就存放a出现的次数。


    image.png
char findFirstChar(char* cha)
{
    char result = '\0';
    // 定义一个数组 用来存储各个字母出现次数
    int array[256];
    // 对数组进行初始化操作
    for (int i=0; i<256; i++) {
        array[i] =0;
    }
    // 定义一个指针 指向当前字符串头部
    char* p = cha;
    // 遍历每个字符
    while (*p != '\0') {
        // 在字母对应存储位置 进行出现次数+1操作
        array[*(p++)]++;
    }
    
    // 将P指针重新指向字符串头部
    p = cha;
    // 遍历每个字母的出现次数
    while (*p != '\0') {
        // 遇到第一个出现次数为1的字符,打印结果
        if (array[*p] == 1)
        {
            result = *p;
            break;
        }
        // 反之继续向后遍历
        p++;
    }
    
    return result;
}

@end

调用:

// 查找第一个只出现一次的字符
char cha[] = "gabaccdeff";
char fc = findFirstChar(cha);
printf("this char is %c \n", fc);

查找两个子视图的共同父视图

  • 要求:
    有C、D两个视图。要查找这两个视图的共同父视图。
    图中箭头代表父视图。如A是C的父视图。
查找两个子视图的共同父视图
  • 思路:
    遍历出两个view的父视图放到两个数组里面。从后往前遍历两个数组中的值。


    查找两个自视图共同的父视图
.h:
@interface CommonSuperFind : NSObject

// 查找两个视图的共同父视图
- (NSArray *)findCommonSuperView:(UIView *)view other:(UIView *)viewOther;

@end

.m:
#import "CommonSuperFind.h"

@implementation CommonSuperFind

- (NSArray  *)findCommonSuperView:(UIView *)viewOne other:(UIView *)viewOther
{
    NSMutableArray *result = [NSMutableArray array];
    
    // 查找第一个视图的所有父视图
    NSArray *arrayOne = [self findSuperViews:viewOne];
    // 查找第二个视图的所有父视图
    NSArray *arrayOther = [self findSuperViews:viewOther];
    
    int i = 0;
    // 越界限制条件
    while (i < MIN((int)arrayOne.count, (int)arrayOther.count)) {
        // 倒序方式获取各个视图的父视图
        UIView *superOne = [arrayOne objectAtIndex:arrayOne.count - i - 1];
        UIView *superOther = [arrayOther objectAtIndex:arrayOther.count - i - 1];
        
        // 比较如果相等 则为共同父视图
        if (superOne == superOther) {
            [result addObject:superOne];
            I++;
        }
        // 如果不相等,则结束遍历
        else{
            break;
        }
    }
    
    return result;
}

- (NSArray  *)findSuperViews:(UIView *)view
{
    // 初始化为第一父视图
    UIView *temp = view.superview;
    // 保存结果的数组
    NSMutableArray *result = [NSMutableArray array];
    while (temp) {
        [result addObject:temp];
        // 顺着superview指针一直向上查找
        temp = temp.superview;
    }
    return result;
}

@end

快速排序

具体看链接快速排序

@implementation QuickSort

//a[]:数组  begin:开始排序的位置  end:结束排序的位置
void  quickSort(int a[],int begin,int end){
    
    if (begin > end) {
        return;
    }
    int i = begin;//左边开始寻找的位置
    int j = end;//右边开始寻找的位置
    
    int key = a[i];//设置左边的第一个值为参考值

    while (i!=j) {//当i和j相遇时,交换相遇位置的值和参考值即可;不相等时,进行位置交换
        
        while (i key) {//从右边开始寻找,找到比参考值小的值,就停止
            
            j--;
        }
        while (i
- (void)viewDidLoad {
    [super viewDidLoad];
     int a[] = {9,8,10,20,7,6,5,11};
     quickSort(a, 0, 7);  
}

求无序数组当中的中位数

方法1:排序算法+中位数:

冒泡、快速、堆排序、二分查找

中位数的定义:
当n为奇数的时候,中位数 = (n -1)/2 的这位数就是中位数。
eg:2、4、6、7、9、20、22 。一共有7位数, 中位数就是第(7-1)/2 = 3位上面的数 7。

当n为偶数的时候,中位数就是中间两位数之和的一半,就是中位数。
中位数 = ((n -1)/2 + ( (n - 1)/2 + 1) )/2

eg:2、4、6、7、9、20、22 、25。一共有8位数, 中位数两位数是7、9 之和的一半8。

方法2:利用快排思想

思路:
已知中位数是哪个位置上的。

  • 数组个数为奇数:(n-1)/2 就是中位
    取数组中的一个值作为关键值,进行快速排序,看他在快速排序后的位置。如果刚好是中位数的位置,中位数就是这个值。

如果位置< (n-1)/2,那么中位数就在这个位置的左边
如果位置> (n-1)/2,那么中位数就在这个位置的右边

又再去新指定的区域找一个关键字值,进行快速排序。重复以上步骤。

  • 数组个数为偶数数:(n-1)/2、 (n-1)/2 +1 两个位置上的数之和的平均数就是中位
@implementation MediaFund

int mediaFund(int a[],int alength){
    
    //找到(n-1)/2位置的数
    int media = (alength - 1)/2;

    int div = partSort(a, 0, alength - 1);
    
    while (div != media) {
        
        if (div < media) {//值在右侧,查找右侧区域
            
            div = partSort(a, div + 1, alength -1);
            
        }else{//值在左侧,查找左侧区域
            
            div= partSort(a, 0, div -1);
        }
        
    }
    
    //如果是偶数,找到(n-1)/2 + 1位置的数
    if (alength%2 == 0) {//数组是偶数个
    
      int newLoc = div + 1;
      int newDiv = partSort(a, newLoc, alength - 1);

        while (newLoc != newDiv) {

            if (newDiv > newLoc) {
                newDiv = partSort(a, newLoc, newDiv - 1);
            }
        }
        printf("数组中的个数为偶数:a[div]:%d~~~[newLoc]:%d\n",a[div],a[newDiv]);
        return (a[div] + a[newLoc])/2;

    }else{//数组中的个数为奇数
        
        printf("数组中的个数为奇数:a[div]:%d",a[div]);
        return a[div];

    }
    
}

//单遍快速排序
int  partSort (int a[],int begin,int end){
    
    int key = a[begin];
    int i = begin;
    int j = end;
    
    while (i != j) {
        
        while (i < j & a[j] > key) {
            j-- ;
        }
        while (i

调用:

//    int a[] = {9,8,10,7,6,5,11};
    int a[] = {9,8,11,7,6,5,10,20};

    //5 6 7 8 9 10 11  (7个数) 中位数为第(7 - 1)/2 = 3位,8
    //5 6 7 8 9 10 11 20 (8个数) 中位数为第4位+第5位之和/2
    
    int div =  mediaFund(a, 8);
    printf("中位数是:%d\n",div);
    printf("排序后的数组是:");
    
    for (int i = 0; i < 8; i++) {
        printf("%d ", a[I]);
    }

你可能感兴趣的:(算法)