排序、KMP算法、队列、栈

一、希尔排序

  1.初次取序列的一半为增量,以后每次减半,直到增量为1(round(n/2)--->1)

  2.每组遍历

  3.组内排序

 1 //希尔排序
 2 int shell_sort(int *data, int len)
 3 {
 4     int gap = 0;
 5     int i = 0, j = 0;
 6     for (gap = len / 2; gap >= 1; gap / 2) //增量---->外层步长控制
 7     {
 8         for (i = gap; i < len; i++) //每组遍历
 9         {
10             int temp = data[i];
11             for (j = i - gap; j >= 0 && temp < data[j]; j = j - gap) //组内排序
12             {
13                 data[j + gap] = data[j];
14             }
15             data[j + gap] = temp;
16         }
17     }
18 
19     return 0;
20 }

 

二、快速排序

  1.第一个值为哨兵,从后面往前面找,找到比它小的,然后替换;从前面往后面找,找到比它大的,然后替换;

  2.然后以第一个key为基准,数据分为两部分,分别是key的左边部分和key右边部分;分别对这两部分的数据进行递归;

//快速排序
int sort(int *data, int left, int right) //每一次递归, 每调用一次, 确定一个key的正确位置
{
    if (left >= right)
        return 0;

    int i = left;
    int j = right;
    int key = data[left];
    while (i < j) //保证出现i==j,即确定了key的位置
    {
        while (i < j && key < data[j]) //从后面往前面走,找到小于key的值,然后替换
        {
            j--;
        }
        data[i] = data[j];

        while (i < j && key >= data[i]) //从前面往后面走,找到大于key的值,然后替换
        {
            i++;
        }
        data[j] = data[i];
    }
    //i == j,此时确定了key的所在顺序的正确位置
    data[i] = key;

    //递归
    sort(data, left, i - 1);
    sort(data, i + 1, right);
    return 0;
}

int quick_sort(int *data, int len)
{
    sort(data, 0, len - 1);
    return 0;
}

 

三、链表常考知识点

  1.单向链表如何找到倒数n个节点

    双指针法:

    (1) p2往后移动N个节点,此时p1和p2之间的距离刚好为N
    (2) 同时往后移动p1,p2,当p2是尾节点时,p1刚好移动到倒数第N个节点
struct Node
{
    int data;
    struct Node *next;
};

struct Node *lastNode(struct Node *head, int n)
{
    struct Node *p1;
    struct Node *p2;
    p1 = head;
    p2 = head;

    int k = n;

    while ((k > 1) && (p2 != NULL))
    {
        p2 = p2->next;
        k--;
    }

    if (p2 == NULL) /*说明链表数目不足n个*/
    {
        return head;
    }

    while (p2->next != NULL) //双指针移动,当p2是尾节点时,p1刚好移动到倒数第N个节点
    {
        p2 = p2->next;
        p1 = p1->next;
    }
    return p1;
}
  

  2.判断链表是否有环?

    快慢指针法:

    (1)慢指针slow每次往前走一步(slow = slow->next),快指针fast每次往前走两步(fast = fast->next->next);

    (2)如果有环,fast一定会先进入环,而slow后进入环。当两个指针都进入环之后,经过一定步的操作之后二者一定能够在环上相遇;

int has_cycle(struct Node *head)
{
    struct Node *fast = head;
    struct Node *low = head;
    while (fast != NULL && fast->next != NULL)
    {
        low = low->next;
        fast = fast->next->next;
        if (low == fast)
        {
            return 1;
        }
    }
    return 0;
}

 

  3.判断两个链表是否交叉,并返回交点

  双指针移动法:   
  长的链表先走abs(len1 - len2)步,此时两个链表剩余的长度一样长,两个链表再同时往后移动,如果有相等则相交;
struct Node *intersect_list(struct Node *headA, struct Node *headB)
{
    struct Node *p1 = headA, *p2 = headB;
    int len1 = 0, len2 = 0;
    while (p1)
        p1 = p1->next, len1++;//获取长度
    while (p2)
        p2 = p2->next, len2++;

    int diff = abs(len1 - len2);
    struct Node *big = len1 >= len2 ? headA : headB;//取得长的链表
    while (diff--)
        big = big->next;

    struct Node *small = len1 < len2 ? headA : headB; //取得短的链表
    while (big != small) //两个链表再同时往后移动,如果有相等则相交
    {
        big = big->next;
        small = small->next;
    }
    return small;
}

 

  4.链表反转

    就地反转,一个头节点,两个指针。
struct Node *reverse_list(struct Node *head)
{
    if (head == NULL)
    {
        return head;
    }
    //新建一个空头节点,连接 head节点
    struct Node *dummy;
    dummy->data = -1;
    dummy->next = head;
    //新建两个指针
    struct Node *prev = dummy->next;
    struct Node *pCure = prev->next;

    while (pCure != NULL)
    {
        prev->next = pCure->next;  //prev连接下一次需要反转的节点,相当于断开pCure,与上一个和下一个节点的连接
        pCure->next = dummy->next; //反转节点pCur,即指向的是prev节点

        dummy->next = pCure; //纠正头结点,指向当前的节点pCur
        pCure = prev->next;  //pCur指向下一次要反转的节点
    }

    return dummy->next;
}

 

四、KMP算法

  字符串匹配算法

  (1)求出公共部分最长的长度;

  (2)下一次对比数组(next数据)

void make_next(const char *pattern, int *next)
{
    int q, k;
    int m = strlen(pattern);

    next[0] = 0;
    for (q = 1, k = 0; q < m; q++)
    {
        while (k > 0 && pattern[q] != pattern[k])
        {
            k = next[k - 1];
        }
        if (pattern[q] == pattern[k])
        {
            k++;
        }
        next[q] = k;
    }
}

int kmp(const char *text, const char *pattern, int *next)
{
    int n = strlen(text);
    int m = strlen(pattern);
    make_next(pattern, next);
    int i, q;
    for (i = 0, q = 0; i < n; i++)
    {
#if 1
        while (q > 0 && pattern[q] != text[i])
        {
            q = next[q - 1];
        }
#endif
        if (pattern[q] == text[i])
        {
            q++;
        }

        if (q == m)
        {
            return i - q + 1;
        }
    }
    return -1;
}

int main()
{
    char *text = "abcabcabcabcabcd";
    char *pattern = "abcabcd";
    int next[20] = {0};
    int idx = kmp(text, pattern, next);
    printf("match pattern:%d\n", idx);
    return 0;
}

 

posted @ 2021-03-13 17:50  MrJuJu  阅读(49)  评论(0编辑  收藏  举报