数据结构1—希尔,KMP(只挂个代码),链表简单题

数据结构1—希尔,KMP,链表简单题

业务代码写了几个月,深感脱离了业务,感觉不剩下啥,特此进行一些基础复习。

希尔排序

希尔排序的核心思想:分组+插排

  • 分组

    以gap = length / 2分组,从第一个元素开始,每间隔gap个元素划分为一组,以此类推。当gap为1时,即每组剩余一个元素,此时排序完成。

  • 组内排序

    通过插入排序来对每组元素进行排序。

/*
 * @param
 *       data : data
 *       length: length of data
 * @return 
 * 		 0:sucess
 */
int shell_sort(int *data, int length) {

    int gap = 0;
    int i = 0, j = 0;
    for (gap = length / 2; gap >= 1; gap /= 2) { // 分组次数

        for (i = gap; i < length; i++) { // 从第gap个元素开始,对其再其对应组内做插入排序

            int temp = data[i];
            for (j = i - gap; j >= 0 && temp < data[j]; j = j - gap) { //组内排序
                data[j + gap] = data[j];
            }

            data[j + gap] = temp;
        }

    }
    return 0;

}

实现细节:

第二个循环:从第gap个元素开始,对于每个元素,都在对应组内做插入排序。data[gap]在第一组,data[gap + 1] 在第二组,以此类推。data[0]与data[gap]先做插入排序,以此类推。在2 * gap个元素的时候,data[0],data[gap]已经排好序了,继续插入即可。

快速排序

老生常谈。每次确定一个元素位置,分治法递归即可。

int sort(int *data, int left, int right) {
    if (left >= right) {
        return 0;
    }

    int i = left;
    int j = right;
    int key = data[left];

    while (i < j) {

        while (i < j && key < data[j]) j--;

        data[i] = data[j];

        while (i < j && key >= data[i]) i++;

        data[j] = data[i];
    }
    // i==j
    data[i] = key;

    sort(data, left, i - 1);
    sort(data, i + 1, right);
}

int quick_sort(int *data, int length) {

    sort(data, 0, length);

}

KMP

KMP算法其实在算法导论里讲的更好(我这只是挂个代码,稀碎的解释可以不用看啦)next数组其实对应着含义不同其实现也不同。

Pattern: abcabcd,后面简称P

Target: abcabcabcabcabcd,后面简称T

预备知识:前缀和后缀。

例如abca

  • 前缀:不包含最后一个字符的前面连续字串 (a,ab,abc)
  • 后缀:不包含第一个字符的后面的连续字串 (a,cd ,bcdc)

核心思想:利用已经部分匹配这个有效信息,让模式串尽量地移动到有效的位置。每次移动相同前后缀的最大长度。

用公式来看就是这样

​ P[0 ~ k-1] == P[j-k ~ j-1]

next:模式串下一次移动长度数组。next[j] = k,P[0~j]中最长相同前后缀长度。

//abcabc
//k = 0
/ q = 1
void make_next(const char *pattern, int *next) {

    int q, k;  //k 前缀,q后缀下标
    int m = strlen(pattern);
    next[0] = 0; // 初始化
    for (q = 1, k = 0; q < m; q++) {
// PS 可以动手画一下
        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++) {// i --> text, q --> pattern
        while (q > 0 && pattern[q] != text[i]) {
            q = next[q - 1];
        }
        
        if (pattern[q] == text[i]) {
            q++;
        }
        
        if (q == m) {
            return i - q + 1;
        }  
    }
}

几道leetcode简单链表题,老生常谈的题目就直接放代码啦。

1.单向链表寻找倒K节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    int kthToLast(ListNode* head, int k) {
        if (!head) {
            return 0;
        }
        ListNode *slow = head, *fast = head;
        while (k-- && fast){
            fast = fast->next;
            
        }
        while(k-- && fast) {
            slow = slow->next;
            fast = fast->next;
            
        }
        return slow->val;
    }
};

2.判断链表有无环

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;

        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow)
            {
                return true;
            }
        }

        return false;
    }
};

3.链表相交

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *A = headA;
        ListNode *B = headB;

        if(!headA||!headB){
            return NULL;
        }
        
        while(headA != headB)
        {
            headA = headA == NULL ? B : headA->next;
            headB = headB == NULL ? A : headB->next;
        }
        return headA;
    }
};

4.反转链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre = NULL;
        ListNode *now = head;

        while(now)
        {
            ListNode *tmp = now->next;
            now->next = pre;
            pre = now;
            now = tmp;
        }
        return pre;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值