第一个一千行总结-数据结构C复习--知识点总结1--一到四章

总结


第一章:

 
数据结构包括:逻辑结构,储存结构, 运算集合
逻辑结构:分为线性(线性表, 栈, 队列, 字符串, 数组, 广义表)
        非线性:树,图,网
储存结构:顺序储存和非顺序储存 线性储存,散列储存,链式储存

算法+数据结构 = 程序

第二章:线性表:


线性表的线性储存 
逻辑结构: 
除了端点以外,所有元素均有一个前驱和一个后继.具有一对一的关系.
存储结构:
一组地址连续的储存单元依次存储

#define MAX 100
typedef struct{
    int elem[MAX];
    int last;
}SeqList;

基本运算:
    
查找: 
按照坐标查找和按照内容查找 

插入:
判插入位置,判满-->找到位置,移动后面的元素-->插入!

删除:
参数:删除的位置序号 
判位置-->将插入元素放到对应变量中-->移动元素

双非递减有序表合并:
元素比较插入-->单表剩余元素插入

2.3线性表的链式存储

单链表: 设头指针H指向第一个结点,前驱结点指针域存放下一个结点的地址
为了方便,在第一个结点之前设立头结点,头指针指向头结点,头结点的指针域存储指向第一个结点的指针

typedef struct Node{//Node为结构标记 
    char data;
    struct Node *next;
}Node, *LinkList; //Node为类型定义
注意:Node*和LinkList同为结构指针, 两者等价.后者习惯指单链表头指针变量,前者定义单链表中结点指针

Attention!!!!!!!

初始化:
InitList(LinkList *L){
    //该处为双指针, 返回值为空, 靠指针传出去!!!
    *L = (LinkList)malloc(szieof(Node));
    (*L)->next = NULL; 

//L指向单链表头结点的指针,*L初始化单链表的头指针变量

建立单链表://头插法 
void CreateFromHead(LinkList L){
    Node *s;
    char c;
    int flag = 1;
    
    while(flag){
        c = getchar();
        if(c != '$'){
            s = (Node *)malloc(sizeof(Node));
            s->data = c;
            s->next = L->next;//L相当于头结点(表头指针)
            L->next = s; 
        } 
        else
            flag = 0;
    }
}

//尾插法
void CreateFromTail(LinkList L){
    Node *s, *r;
    char c;
    int flag = 1;
    
    r = L;
    while(flag){
        c = getchar();
        if(c != '$'){
            s = (Node *)malloc(sizeof(Node));
            s->data = c;
            r->next = s;
            r = s; 
        } 
        else{
            flag = 0;
            r->next = NULL;
        }
    }
}

查找:
按照序号和按照值,和线性表差不多,判空条件改为while(p)
求长度:...

单链表插入:
判断插入位置合理性-->插入(一般都是头插,类似语句如下:s->next = pre->next; pre->next = s)

删除:
关键语句:r = pre->next;//赋值 
        pre->next = r->next;
        *e = r->data;
        free(r);//!!!

合并两个有序单链表:
思想:不用新分配空间,直接比较数据修改指针,把其中的一个表头当作新表表头...

LinkList MergeList(LinkList LA, LinkList LB){
    LinkList LC;
    Node *pa, *pb, *r;
    
    LC = LA;
    pa = LA->next;
    pb = LB->next;
    r = LC;
    
    while(pa && pb){
        if(pa->data >= pb->data){
            r->next = pa;
            r = pa;
            pa = pa->next;
        }
        else{
            r->next = pb;
            r = pb;
            pb = pb->next;
        }
    }
    if(pa)
        r->next = pa;
    else
        r->next = pb;
    
    r->next = NULL;
    free(r);
    free(LB);
    return(LC); //return LC;


循环链表:将单链表最后一个结点指针域NULL改为指向表头结点
单循环链表判断条件: p != L或 p->next != NULL;

初始化循环单链表:
InitCLinkList(LinkList *CL){
    *CL = (LinkList)malloc(sizeof(Node));
    (*CL)->next = *CL;//注意CL是指针(地址), *CL为结点,(或者说结点指针, 就是一般的结点)!!!!!!!!!!!! 

Attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
建立循环单链表:易错 
void CreateCLinkList(LinkList CL){
    //尾插法
    Node *rear, *s;
    char c;
    
    rear = CL; //典型步骤
    c = getchar();
    
    while(c != '$'){
        s = (Node *)malloc(sizeof(Node));
        s->data = c;
        rear->next = s;
        rear = s;//典型
        c = getchar();//!!别忘记了 
    } 
    rear->next = CL;// 

循环单链表合并:
LinkList Merge(LinkList LA, LinkList LB){
    Node *p, *q;//带头结点
    
    p = LA;
    q = LB;
    
    while(p->next != LA) p = p->next;
    while(q->next != LB) q = q->next;
    
    p->next = LB->next;
    q->next = LA;
    
    free(LB);
    return LA; 
}

//稍难,带尾指针的带头结点循环内单链表合并算法

LinkList Merge_2(LinkList LA, LinkList LB){
    //LA LB为尾指针,所以LA->next and LB->next 为头结点
    Node *p;
    
    p = LA->next;//p暂时保存LA头结点地址
    LA->next = LB->next->next;//指向LB第一个结点
    free(LB->next);
    LB->next = p;
    
    return LB;//返回新的循环链表的尾指针 

LinkList Merge_2(LinkList A, LinkList B){
    Node *q;
    
    q = B->next;
    B->next = A->next->next;
    free(A->next);
    A->next = q;
    
    return A; 

双向链表:

typedef struct DNode{
    int data;
    struct DNode *prior, *next;
}DNode, *DoubleList;


插入:
//需要改变四个指针

int DLinkInsert(DoubleList L, int i, int e){
    
    DNode *s, *p;
    
    //判断插入位置是否合法
    p = L;
    for(; i > 0 && p; i--)
        p = p->next;
    //p最终指向待插入位置
    if(!p) return FALSE;
     
    s = (DNode *)malloc(sizeof(DNode));
    s->data = e;
    
    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;
    p->prior = s;
    
    return OK; 

删除相似:
判断插入位置-->找到删除节点->删除数据存入指针变量->改变指针->返回TRUE
关键步骤:
*e = p->data;
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);

静态链表:相比于动态链表(借助函数malloc和free),定义较大的结构数组,存放data和游标cursor
多次插入和删除造成链表假满,原因是未对删除元素空间进行回收.将所有删除和未分配的结点空间
通过游标链形成空闲结点链表...


线性表的应用:
    
一元多项式的表示及相加

typedef struct Polynode{
    int coef;//系数
    int exp;//指数
    struct Polynode *next; 
}Polynode, *Polylist; 

尾插法建立:...

相加运算:

void Polyadd(Polylist polya, Polylist polyb){
    Polynode *p, *q, *tail, *temp;
    int sum;
    
    p = polya->next;
    q = polyb->next;//p,q分别指向第一个结点;
    tail = p;
    
    while(p && q){
        if(p->exp < q->exp){
            //尾插
            tail->next = p;
            tail = p;
            p = p->next; 
        }
        else if(p->exp > q->exp){
            tail->next = q;
            tail = q;
            q = q->next;
        }
        else{
            //指数相等,判断系数之和是否为零
            //为零,分别走下一个结点,同时释放p,q;不为零, ....
            sum = p->coef + q->coef;
            if(sum){
                p->sum = sum;
                tail->next = p;
                tail = p;
                p = p->next;
                 
                temp = q;
                q = q->next;
                free(temp);
            } 
            else{
                temp = p;
                p = p->next;
                free(temp);
                
                temp = q;
                q = q->next;
                free(q);
            }
        }
    } 
    //值得注意的是,也许其中一个链表数据并没有走完
    if(p)
        tail->next = p;
    else
        tail->next = q; 

经典算法:
    
删除顺序表中所有值为x的元素,时间复杂度尽可能小
思想:避免直接扫描-->删除-->移动...
在原来表的基础上构造新表,方法:若是不等于x,那么直接复制到新表;等于就跳过.注意的是新表不用另外声明. 

单链表第一个存储元素的值划分单链表为两半, 小于放该元素前面,大于相反
//默认有头结点 
void divide_2(LinkList L){
    if(!L->next) return;
    
    Node *p, *q, *pre, *s;
    
    s = L->next;//r指向划分结点
    pre = s;
    p = s->next;
    
    while(p){
    //p!=NULL
    q = p->next;//指针跟踪技术
    if(p->data < s->data){
        //头插,利用pre的指针跟踪
        pre->next = p->next;//pre后继连接到q
        //头插 
        p->next = L->next;
        L->next = p;
        
        p = q; 
    } 


第二章总结:
存储密度:顺序表为百分百,链表会低很多
优缺点:顺序表为随机存储,单链表需要从头查找.插入删除少就顺序表

线性链表分为:
    带头结点的单链表!!!很重要!:特点只能从前往往后寻找
    带头结点的循环单链表:寻找一个结点的前驱时间耗费O(n);
    带尾指针的循环单链表:寻找尾结点和头结点方便
    带头结点的双向循环链表:前驱和后继都好找但是储存密度相对较低. 
    

第三章 限定性线性表--栈和队列!必考!!!

 

栈:单向插入和删除,叫做入栈和出栈  后进先出的特点

定义;
typedef struct {
    int elem[MAX];
    int top;//空为-1 
}SeqStack;//顺序栈

初始化:栈顶置为-1
进栈:判满-->栈顶++ ->进栈
出栈:判空-->栈底-- ->出栈 
!!
//判空
bool IsEmpty(SeqStack *S){
    if(S->top == -1)
        return true;
    else
        return false;

//出栈
int Pop(SeqStack *S, int *e){
    if(IsEmpty(S))
        return -1;
    
    *e = S->elem[S->top];
    S->top--;
    return 1;

多栈共享技术:双端栈,栈底分别为两端,判满:S->top[0] + 1 == S->top[1];判空: S->top[0] == 0,S->top[1] == MAX-1;

链栈:
定义:
typedef struct node{
    int data;
    struct node *next;
}LinkStackNode;

typedef LinkStackNode* LinkStack

//进栈:top为头结点 
int Push(LinkStack top, int x){
    LinkStackNode *temp;
    temp = (LinkStackNode *)malloc(sizeof(LinkStackNode));
    if(temp == NULL){
        printf("申请空间失败\n");
        return FALSE;
    }
    temp->next = x;
    temp->next = top->next;
    top->next = temp;
    return TRUE;

//出栈
int Pop(LinkStack top,int *x){
    LinkStackNode *temp;
    temp = top->next;
    if(temp == NULL){
        return FALSE;
    }
    top->next = temp->next;
    *x = temp->data;
    free(temp);
    return TRUE;

//多栈运算 略 
#define N 10
typedef struct node{
    int data;
    struct node *next;
}LinkStackNode, *LinkStack; 
LinkStack top[N];
//top[i]分别是十个栈中每个栈的栈顶  


//括号匹配 
void BracketMatch(char *str){
    Stack S;
    int i;
    char ch;
    //初始化
    InitStack(&S);
    for(i = 0; str[i] != '\0'; i++){
        switch(str[i]){
            case '[':
            case '{':
            case '(':
                Push(&S, str[i]);
                break;
            case ')':
            case ']':
            case '}':
                if(IsEmpty(&S)){
                    printf("右括号多余!\n");
                    break;
                }    
                else{
                    GetTop(&S, &ch);
                    if(Match(ch, str[i])){
                        Pop(&S, &ch);
                    }
                    else{
                        printf("括号不匹配\n");
                        return;
                    }
        }
        }
    } 
    if(IsEmpty(&S)){
        printf("括号匹配成功!\n");
        return;
    }
    else
        printf("左括号多余\n");

//表达式求值 略 
int ExpEvaluation(){
    InitStack(&OPTR);//运算符栈 
    InitStack(&OVS);//运算数栈 
    Push(&OPTR, '#');
    printf("\n\nPlease enter an expression(End with '#'):");
    ch = getchar();
    
    while(ch == '#' || GetTop(OPTR)!='#'){
        if(!In(ch, OPSet)){
            n = GetNumber(ch);
            Push(&OVS, n);
            ch = getchar();
        }
        else{
            switch(Compare(ch, GetTop(OTPR))){
                case '>':Push(&OPTR, ch);
                    ch = getchar();
                    break;
                case '=':
                case '<':
                    Pop(&OPTR, &op);
                    Pop(&OVS, &a);
                    Pop(&OVS, &b);
                    v = Execute(a, op, b);
                    Push(&OVS, v);
                    break;
            }
        }
    }
    v = GetTop(OVS);
    return (v);

栈与递归:
常见:斐波那契数列, 汉诺塔问题, 阶乘...

阶乘递归:
int f(int n){
    if(n == 0) 
        return 1;
    else
        return n * f(n-1);

斐波那契:
Fib(int n){
    if(n == 0 || n == 1)
        return n;
    else
        return Fib(n-1) + Fib(n-2);


队列:一端进去,另一端出来 先进先出.
!!!插入一端为队尾, 出去一端为队头,所以插入用尾插!!!!!!!!!!!!!!!!!!!!!!!!!!

链队列:
定义:
typedef struct Node{
    int data;
    struct Node *next;
}LQNode;

typedef struct{
    LQNode *front;
    LQNode *rear;
}LQ;//LinkQueue

初始化:
int InitQueue(LQ *Q){
    Q->front = (LQNode *)malloc(sizeof(Node));
    
    if(Q->front){
        Q->rear = Q->front;
        Q->front->next = NULL;
        return 1; 
    }
    return -1;

入队://这个不太好理解,需要画图 
int EnterQueue(LQ *Q, int x){
    LQNode *new_node;
    
    new_node = (LQNode *)malloc(sizeof(LQNode));
    if(!new_node) return -1;
    
    new_node->data = x;
    new_node->next = NULL;
    Q->rear->next = new_node;//尾插 
    Q->rear = new_node;
    
    return 1; 

循环队列:....


//辗转相除法和排队等待问题 
int fun(int m, int n){
    int r;
    if(n > m){
        return fun(n, m);
        //相与交换位置 
        //多次辗转相除找出最大公约数 
    }
    else if(n == 0){
        return m;
    }
    else{
        r = m % n;
        return (fun(n, r));
    }
}

int fun(int m, int n){
    int r;
    
    do{
        r = m % n//分母较大就相当于执行交换值的操作;
        m = n;
        n = r;
    }while(r != 0);
    return m;
}

void seedoctor(){
    InitQueue(&Q);
    flag = 1;
    while(flag){
        printf("Please enter the code:");
        ch = getch();
        switch(ch){
            case 'a':
                printf("\n病历号:");
                scanf("%d", &n);
                EnterQueue(&Q, n);
                break;
            case 'n':
                if(IsEmpty){
                    DeleteQueue(&Q, &n);
                    printf("病历号为%d号的就诊\n", n);
                } 
                else 
                    printf("无病人等待"); 
                break
            case 'q':
                printf("今天停止挂号, 以下病人依次就诊.");
                while(!IsEmpty){
                    DeleteQueue(&Q, &n);
                    printf("%d    \n", n);
                }
                flag = 0;
                break;
            default:
                printf("输入错误.\n"); 
        }
    }
}  

第三章总结:

栈:先进后出; 顺序栈可能产生上溢,链栈不会. 

队列:先进先出; 链队列设头指针和尾指针,封装在一个结构体里面.


第四章:串


字符串:双引号括起来.....空串:就是一对引号

定长顺序串:静态结构, 地址连续存储单元存储字符串序列
定义:
typedef struct{
    char ch[MAX];
    int len;
}SString;

插入:插入位置position会将已经有的串L分为两个部分i,j,新插入的串s会导致以下三种情况
1. 插入后仍然长度小于MAX
2. 插入后j串溢出一部分
3. 插入后j串全部溢出, s溢出一部分

int SStringInsert(SString *s, int pos, SString t){
    int i;
    //判插入位置合理性 
    if(pos < 0 || pos > s->len) return -1;
    
    //第一种情况, 先将后串后移,再插入
    if(s->len + t.len <= MAX){//注意的是一个是类似字符串指针, 一个用点运算符
        //后移
        for(i = pos + t.len; i < t.len + s->len; i++)
            s[i] = s[i-t.len];
        //复制 
        for(i = pos; i < pos + t.len; i++)
            s[i] = t.ch[i-pos];
        s->len += t.len; 
    }
    else if(pos + t.len <= MAX){
        for(i = MAX - 1; i > pos; i--)
            s[i] = s[i - t.len];
        
        for(i = pos; i < pos + t.len; i++)
            s[i] = t.ch[i-pos];
        s->len = MAX - 1;
    } 
    else{
        for(i = pos; i < MAX; i++)
            s[i] = t.ch[i-pos];
        s->len = MAX - 1; 
    }
    return 1;//#define OK 1; return OK;

//Delete
int StrDelete(SString *s, int pos, int len){
    //从串中删除从pos位置起的len长度的字符
    int i;
    
    if(pos < 0 ||pos > (s->len-len)) return 0;
    
    for(i = pos + len; i < s->len; i++)
        s->ch[i-len] = s->ch[i];
        
    s->len -= len;
    
    return 1; 
}

串比较 
//Compare
int StrCompare(SString s, SString t){
    int i=0;
    for(i = 0; i< s.len && i < t.len; i++)
        if(s.ch[i] != t.ch[i])
            return (s.ch[i] - t.ch[i]);
    return s->len-t.len;//注意返回值
    //如果前者大于后者, 第一个return返回正;后者大, 返回负数
    //前面能够完全匹配, 那么第二个return比较字符串长度 


最基础的BF算法 
//定位函数(布鲁特-福斯算法)
int StrIndex(SString s,int pos, SString t){
    int i, j ,start;
    //对s字符串一轮一轮的从pos字符开始和t字符串比较, 比较不成功则start向后移
    start = pos;
    i = start;
    j = 0;
    while(i < s.len && j <t.len){
        if(s.ch[i] == t.ch[j]){
            i++;
            j++;
        }
        else{
            start++;
            i = start;
            j = 0; 
        }
    }
    if(j >= t.len) return start;
    else return -1; 

堆串:
定义: 
typedef struct{
    char *ch;
    int len;
}HString;

存储方式有效率, 但是程序执行过程中会不断的销毁和生成新串!!!
//插入 
int StrInsert(HString *s, int pos, HString *t){
    int i;
    char *p;
    
    if(pos < 0 || pos > s->len || s->len == 0) return 0;
    //为新串分配空间 
    p = (char *)malloc(sizeof(s->len + t->len));
    if(!p) return 0;
    //旧的前部分复制到新 
    for(i = 0; i < pos; i++)
        p[i] = s->ch[i];
    //复制t 
    for(i = pos; i< pos +t->len; i++)
        p[i] = t->ch[i-pos];
    //复制旧的串后部分 
    for(i = pos; i<s->len;i++ )
        p[i+s->len] = s->ch[i];
        
    s->len += t->len;
    
    !!!!!!!!!!!!!!!!!!!!!!!!!下一步!!!!!!!!!!!!!!!!!!!!
    字符串指针直接复制, 不是普通数组不用strcpy() 
    s->ch = p;
    
    return 1;
}

//赋值
int StrAssign(HString *s, char *tval){
    int len, i = 0;
    if(s->len == 0)return 0;
    while(tval[i] != '\0') i++;
    //得到tval字符串的长度
    len = i;
    if(len){
        s->ch = (char *)malloc(sizeof(len));
        if(!s->ch) return 0;
        for(i = 0; i< len; i++)
            s->ch[i] = tval[i];
        s->len = len;
        return 1;
    } 
    else
        s->ch = NULL;
        return 1;

//块链串
#define MAX 4
typedef struct Block{
    char ch[MAX];//data域, 结点大小, 指的是存放字符的个数 
    struct Block *next;//链域, 指的是link域占用字符个数 
}Block; 

//储存密度 data占用存储位/实际为串分配存储位 存储密度越小运算处理越方便
//MAX == 1时, 就是一个普通的线性链表 
typedef struct{
    Block *head;
    Block *tail;
    int len;
}BLString;

icoding例题改编测试!!!!

#include <stdlib.h>
#include <stdio.h>
#define BLOCK_SIZE 4    
#define BLS_BLANK '#'   // 用于空白处的补齐字符!!!!!!!

typedef struct _block {
    char ch[BLOCK_SIZE];    //块的数据域
    struct _block *next;    //块的指针域
} Block;

typedef struct {
    Block *head;        // 串的头指针
    Block *tail;        // 串的尾指针
    int len;            // 串的当前长度
} BLString;

//字符串初始化函数:
void blstr_init(BLString *T) {
    T->len = 0;
    T->head = NULL;
    T->tail = NULL;
}
//这些定义已包含在头文件 dsstring.h 中,请实现块链串的子串查找操作:
//
//bool blstr_substr(BLString src, int pos, int len, BLString *sub);
//src为要查找的字符串
//pos为子串开始的下标
//len为子串的长度
//sub在函数调用运行前指向一个已经初始化好的空串,在函数返回时,sub指向串src从第pos个字符起长度为len的子串
//函数查找成功返回true,参数不正确返回 false

#include "dsstring.h"
#include <stdio.h>
#include <stdlib.h>
//函数声明:长度判断很多写法,大多数不同的编译器都会各种报错,这种不是最简便的但是一般不会报错 
int len(const char* s)
{
    int q = 0;
    while (*s != '\0') {//while(*s)
        q++;
        s++;
    }
    return q;
}

int StrAssign(BLString* S, const char* cstr)
{
    //将串cstr存入S中去, S是块链串 
    int i, j, k, len;
    Block *p, *q;
    
    len = strlen(cstr); /*len为链串的长度 */
    if (len == 0)
        return 0;
        
    S->len = len;
    //整除哈!!  8 / 5 = 1
    j = len / BLOCK_SIZE; /*j为链串的结点数 */
    if (len % BLOCK_SIZE)
        j++;
        
    for (i = 0; i < j; i++) {
        p = (Block*)malloc(sizeof(Block)); /*动态生成一个结点*/
        if (!p)
            return 0;
            
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!字符串重点 
        for (k = 0; k < BLOCK_SIZE && *cstr; k++) /*将字符串ctrs中的字符赋值给链串的数据域*/
            *(p->ch + k) = *cstr++;//p->ch[k] = cstr[xxx] 
        
        //指针跟踪 
        if (i == 0) /*如果是第一个结点*/
            S->head = q = p; /*头指针指向第一个结点*/
        else {//尾插,q为尾结点 
            q->next = p;
            q = p;
        }
        if (!*cstr) /*如果是最后一个链结点*/
        {
            S->tail = q; /*将尾指针指向最后一个结点*/
            q->next = NULL; /*将尾指针的指针域置为空*/
            for (; k < BLOCK_SIZE; k++) /*将最后一个结点用'#'填充*/
                *(q->ch + k) = BLS_BLANK;
        }
    }
    return 1;
}
bool blstr_substr(BLString src, int pos, int len, BLString* sub)
{
    char* t;
    if (pos < 0 || pos >= src.len || len < 1)
        return false;
    int n = pos / BLOCK_SIZE, h = pos % BLOCK_SIZE;
    Block* temp = src.head;
    for (int i = 0; i < n; i++) //假装到初始节点
    {
        temp = temp->next;
    }
    char str[100];
    int i = 0;
    while (i < len) {
        if (h >= BLOCK_SIZE) {
            temp = temp->next;
            h = 0;
        } else {
            if (!temp || temp->ch[h] == BLS_BLANK)
                break;
            str[i++] = temp->ch[h++];
        }
    }
    str[i] = '\0';
    StrAssign(sub, str);
    return true;
}

//算法BF and KMP 
略过........ 
//BF 回溯算法
int StrIndex(SString s, int pos, SString t){
    int i, j;
    if(t.len == 0)
        return (0);//空串任意串的字串
        
    i = pos;
    j = 0;
    
    while(i < s.len && j < t.len){
        if(s[i] == t[j]){
            i++; j++;
        }
        else{
            i = i-j+1; //关键 
            j = 0;
        }
    }
    if(j >= t.len)
        return (i-j);
    else
        return -1; 
}

//KMP
//next
void GetNext(SString t, int next[]){
    int j, k;
    j = 0;
    k = -1;
    next[0] = -1;
    while(j < t.len-1){
        if(k == -1|| t.data[j] == t.data[k]){
            j++;k++; next[j] = k;
        }
        else{
            k = next[k];
        }
    }
}

//KMP
int StrIndex_KMP(SString s, int pos, SString t, int next[]){
    int i, j;
    if(t.len == 0) return 0;
    i = pos;
    j = 0;
    while(i<s.len && j<t.len){
        if(j == -1 || t.data[i] == s.data[j]){
            i++;j++;
        }
        else
             j = next[j];
        
    }
    if(j>=t.len)
        return i-t.len;
    else
        return -1; 
}

第四章总结:
字符串是特殊的线性表, 元素为字符.
区分:定长顺序串(静态储存),堆串(多次分配销毁),块链串(链表)
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运维进化论:微盟“删库跑路”给我们的启示

作者&#xff1a;茹炳晟&#xff0c;软件质量和研发工程效能专家事件背景微盟是国内移动互联网营销引领者&#xff0c;中国最大的微信公众智能服务平台&#xff0c;基于微信为企业提供开发、运营、培训、推广一体化解决方案&#xff0c;帮助企业实现线上线下互通&#xff0c;社…

[蓝桥杯2016决赛]阶乘位数-数论

题目描述 9的阶乘等于&#xff1a;362880 它的二进制表示为&#xff1a;1011000100110000000 这个数字共有19位。 请你计算&#xff0c;9999 的阶乘的二进制表示一共有多少位&#xff1f; 输出 输出一个整数表示答案 知识点: 整数m在k进制下&#xff0c;有多少位&#xff1f; …

拦截器如何获取@requestbody_分布式系统中如何优雅地追踪日志(原理篇)

分布式系统中日志追踪需要考虑的几个点&#xff1f;需要一个全服务唯一的id&#xff0c;即traceId&#xff0c;如何保证&#xff1f;traceId如何在服务间传递&#xff1f;traceId如何在服务内部传递&#xff1f;traceId如何在多线程中传递&#xff1f;我们一一来解答&#xff1…

数组合并假设有 n 个长度为 k 的已排好序(升序)的数组,请设计数据结构和算法,将这 n 个数组合并到一个数组,且各元素按升序排列。即实现函数-C-icoding-排序-数据结构

数组合并 假设有 n 个长度为 k 的已排好序&#xff08;升序&#xff09;的数组&#xff0c;请设计数据结构和算法&#xff0c; 将这 n 个数组合并到一个数组&#xff0c;且各元素按升序排列。即实现函数&#xff1a; void merge_arrays(const int* arr, int n, int k, int* out…

.NET Core开发实战(第11课:文件配置提供程序)--学习笔记

11 | 文件配置提供程序&#xff1a;自由选择配置的格式文件配置提供程序Microsoft.Extensions.Configuration.IniMicrosoft.Extensions.Configuration.JsonMicrosoft.Extensions.Configuration.NewtonsoftJsonMicrosoft.Extensions.Configuration.XmlMicrosoft.Extensions.Conf…

前端demo_【前端3分钟】Script Error产生的原因和解法

Script Error对于前端开发者相信都不陌生&#xff0c;而且由于没有具体错误堆栈和代码行列号&#xff0c;成为可能是最神秘的错误之一。下面介绍Script Error产生的原理和解决办法。1、Script Error是如何产生的跨域资源引用假如&#xff1a;abc.com 下的页面引用了属于 http:/…

第二个一千行总结-数据结构C复习--知识点总结2--五到七章

第五章 数组与广义表 n维数组看作数据元素为n-1维数组的线性表 数组地址计算:略 特殊矩阵压缩: 三角矩阵;三对角矩阵(带状矩阵); 稀疏矩阵:存储数据总量小于百分之三十 稀疏矩阵用三元组(行,列,值)储存,定义如下: typedef struct{ int row, col;//行,列 int e; }…

基于Abp VNext框架设计 - Masstransit分布式消息

abp 通过IDistributedEventBus接口集成自IEventBus实现分布式事件消息的发布订阅。IEventBus在什么时机触发PublishAsync?当前UnitOfWork完成时&#xff0c;触发IEventBus的PublishAsync在没有事务环境下&#xff0c;同步调用IEventBus的PublishAsyncabp 默认实现基于RabbitMq…

[蓝桥杯2018决赛]换零钞-枚举

题目描述 x星球的钞票的面额只有&#xff1a;100元&#xff0c;5元&#xff0c;2元&#xff0c;1元&#xff0c;共4种。 小明去x星旅游&#xff0c;他手里只有2张100元的x星币&#xff0c;太不方便&#xff0c;恰好路过x星银行就去换零钱。 小明有点强迫症&#xff0c;他坚持要…

16进制数用空格分开 tcp_面试时,你是否被问到过TCP/IP协议?

点击蓝字关注我们看到这句话&#xff0c;有没有感到很熟悉呀&#xff1f;相信很多人在面试的时候都被要求&#xff0c;很多人会觉得我们在实际开发中一般用不到这些知识&#xff0c;所以对这些东西不屑一顾。但是小编认为想要成为一个完美的网工,那么对这些基础知识必须要有一定…

直接使用汇编编写 .NET Standard 库

前言Common Language Runtime&#xff08;CLR&#xff09;是一个很强大的运行时&#xff0c;它接收 Common Intermediate Language&#xff08;CIL&#xff09; 的输入并最终产生机器代码并执行。CIL 在 CLR 上相当于 ASM 汇编代码的存在。CLR 之上的语言 C#、F#、VB.NET 等语言…

[蓝桥杯2016决赛]七星填数-next_permutation枚举

题目描述 如下图所示&#xff1a; 在七角星的14个节点上填入1~14 的数字&#xff0c;不重复&#xff0c;不遗漏。要求每条直线上的四个数字之和必须相等。 图中已经给出了3个数字。请计算其它位置要填充的数字&#xff0c;答案唯一。 填好后&#xff0c;请提交绿色节点的4个数…

python的argsort函数_python——argsort函数

numpy中argsort函数用法&#xff0c;有需要的朋友可以参考下。在Python中使用help帮助>>> import numpy>>> help(numpy.argsort)Help on function argsort in module numpy.core.fromnumeric:argsort(a, axis-1, kindquicksort, orderNone)Returns the indic…

第三个一千行+500行总结-数据结构C复习--知识点总结3--七到九章

第七章 (接知识点总结2) 图 图的遍历: //深度优先搜索 #define OK 1 #define True 1 #define Error -1 #define False 0 typedef enum{DG, DN, UDG. UDN}Graph; int visited[MAX]; //Graph代表图的一种存储结构比如邻接表,邻接矩阵 void TranverseGraph(Graph g){ int…

系统蓝屏的几种姿势,确定不了解下么?

前言在 蓝屏&#xff08;BSOD&#xff09;转储设置&#xff0c;看本文就够了&#xff01;这篇文章里比较详细的介绍了蓝屏转储设置。做好设置后&#xff0c;我们就可以在需要的时候使系统蓝屏了。本文介绍几种使系统蓝屏的办法&#xff0c;当然肯定还有其它办法&#xff0c;如果…

最长公共子串-dp

题目: 给定两个字符串&#xff0c;求出它们之间最长的相同子字符串的长度。 公共子串和公共子序列不同&#xff0c;公共子序列不要求连续&#xff0c;但公共子串必须是连续的。如: A “helloworld” B “loop” A和B的最长公共子序列是"loo",但最长公共子串是&quo…

the python challenge_The Python Challenge 谜题全解(持续更新)

Python Challenge(0-2)是个很有意思的网站&#xff0c;可以磨练使用python的技巧&#xff0c;每一关都有挑战&#xff0c;要编写相应的代码算出关键词&#xff0c;才可以获取下一关的url&#xff0c;还是很好玩的QAQLEVEL 0显然是计算图片中的\(2^{38}\)&#xff0c;结果为2748…

智能对话引擎:两天快速打造疫情问答机器人

01微软AI技术开源知识库疫情机器人近一个月来&#xff0c;“新冠肺炎疫情”成了所有人的热点话题&#xff0c;抗击疫情的战役在全国紧张有序地进行着。随着全国各地的企业陆续复工&#xff0c;怎样防范、保护自己和家人成了当下每个人的焦点。为了配合奋战在一线的医护人员打赢…

数码管

题目背景 小明的单片机上面的LED显示屏坏掉了&#xff0c;于是他请你来为他修显示屏。 屏幕上可以显示0~9的数字&#xff0c;其中每个数字由7个小二极管组成&#xff0c;各个数字对应的表示方式如图所示&#xff1a; 题目描述 为了排除电路故障&#xff0c;现在你需要计算&am…

fh 幅频特性曲线怎么画fl_初学者怎么练习线条?教你如何画出流畅线条的技巧...

初学者怎么练习线条&#xff1f;怎样才能画出流畅线条&#xff1f;画出流畅线条有哪些技巧&#xff1f;想必这些问题都是绘画初学者们比较伤脑筋的问题&#xff0c;那么到底怎样才能画出流畅线条呢&#xff1f;今天灵猫课堂老师就在网络上收集整理了关于初学者怎么练习线条&…