链表的算法面试题总结

来源:互联网 发布:布里克中士升级数据 编辑:程序博客网 时间:2024/06/05 08:28

1、单链表的创建和遍历
 2、求单链表中节点的个数(太简单,就不写了)
 3、查找单链表中的倒数第k个结点(剑指offer,题15)
 4、查找单链表中的中间结点
 5、合并两个有序的单链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)
 6、单链表的反转【出现频率最高】(剑指offer,题16)
 7、从尾到头打印单链表(剑指offer,题5)
 8、判断单链表是否有环
 9、取出有环链表中,环的长度
 10、单链表中,取出环的起始点(剑指offer,题56)。本题需利用上面的第8题和第9题。
 11、判断两个单链表相交的第一个交点(剑指offer,题37)

完整代码(一)

#include <stdio.h>#include <stdlib.h>typedef char ElemType;/*    1,创建链表,初始化,遍历    3,找到倒数第k个节点。    4,找到中间节点。    6,逆置要求空间复杂度o(1),时间复杂度o(n)*//*    创建链表:创建链表增删*//**    链表节点*/typedef struct knode{    ElemType data;    struct knode *next;//  struct knode *prior;}linknode;// 创建头结点linknode *create(){    linknode *root;    root = (linknode *)malloc(sizeof(linknode));    root->next = NULL;//  root->prior = NULL;    return root;}// 从头部开始添加节点void insert(linknode *s,int i) {    linknode *p;    while(i != 0) {        p = (linknode *)malloc(sizeof(linknode));        p->next = s->next;//      p->prior = s;        s->next =p;//      printf("输入插入的数据:");        scanf("%c",&p->data);               // 前面不能有其他输入流        i--;    }}// 遍历节点,并且返回节点长度。int ergodic(linknode *s){    int length = 0;    s = s->next;    if(s == NULL) return length;    while(s){        printf("%c ",s->data);        s = s->next;        length++;    }    return length;}// 长度int length(linknode *s){    int len = 0;    s = s->next;    if(s == NULL) return len;    while(s){        s = s->next;        len++;    }    return len;}// 2.1)单链表,找到倒数第k个节点。并且输出。int find(linknode *s,int k){    int len,t;    len = length(s);    s = s->next;    if(s == NULL) return 0;    if(len < k) return 0;    t = len - k;    while(t-1 != 0){        s = s->next;        t--;    }    s = s->next;    printf("第k个元素是%c\n",s->data);    return 1;}/*    2.2)链表找到倒数第k个节点。*/int finds(linknode *s,int k){    linknode *q,*p;    q=p=s;    if(s == NULL) return 0;    while(q != NULL && (k-1) != 0){     //  q 到顺数第k个节点。        q = q->next;        k--;        return 0;    }    while(q->next != NULL && p != NULL){    // q->next如果为空,就表示结束向前移动。        q = q->next;        p = p->next;    }    printf("中间的节点:%c\n",p->data);    return 1;}// 输出链表中间节点。void middle(linknode *s){    int len,t;    len = length(s);    if(len % 2 == 1){        t = len/2 +1;    }else{        t = len/2;    }    while(t != 0){        s = s->next;        t--;    }    printf("这是中间的节点%c\n",s->data);}// 链表逆置,空间O(1)/**/linknode *reverse(linknode *s){    linknode *head,*p,*r,*d;    d = r = head = s;           s = head->next;         // s 指向第一个节点。    while(s != NULL) {        p = s->next;     // 让p指向s的下一个节点。            s->next = head;  // s 节点逆指向。        head = s;       // head 节点向前移动。        s = p;          // s节点向前移动,最后结果 s = NULL, p = NULL    }    d = r->next;        // d 就是为了找到最后一个节点。让它的next = NULL。r->next和最后一个节点在此时是双向的。    d->next = NULL;     // 尾节点next为NULL     r->next = head;    return r;}// 合并两个有序链表,非递归方法。void main(){    linknode *s,*r;    s = create();    // 插入    int i,length;    printf("插入节点的个数:");    scanf("%d",&i);    insert(s,i);    //遍历    length = ergodic(s);    printf("链表的长度%d\n",length);    find(s,3);    //输出中间节点    middle(s);    //查倒数第k个节点    finds(s,3);    //逆置    r = reverse(s);    ergodic(r);    printf("\n");}

完整代码(二)

/**5, 链表的合并。7,(在不改变链表结构的前提下)逆序输出单链表的值*/#include <stdio.h>#include <stdlib.h>#include <iostream>using namespace std;typedef char ElemType;typedef struct node{    ElemType data;    struct node *next;}linknode;// 创建链表linknode *create(){    linknode *root;    root = (linknode *)malloc(sizeof(linknode));    root->next = NULL;    root->data = NULL;    return root;}// 初始化链表void init(linknode *s,int k){    linknode *p;    cout<<"输入有序的字符串:";    for(int i = 0; i < k; i++){        p = create();        cin>>p->data;        s->next = p;        s = p;    }}// 遍历,带头结点的。void pt(linknode *s){    cout<<"输出内容:";    s = s->next;    while(s){        cout<<s->data;        s = s->next;    }    cout<<endl;}// 遍历不带头结点的。void pts(linknode *s){    cout<<"输出内容:";    while(s){        cout<<s->data;        s = s->next;    }    cout<<endl;}//merge 合并有序链表(有序)(带头结点的)linknode *merge(linknode *s,linknode *r){    linknode *p,*p1,*p2,*root;    // 两个链表都非空    if(s->next == NULL) {        return r;    }    if(r->next == NULL) {        return s;    }    p1 = s->next;    p2 = r->next;    // 确定那个链表,成为新的链表头    if(p1->data <= p2->data){        root = p1;        p = p1;             // p指向新选出的节点。        p1 = p1->next;    }else{        root = p2;        p = p2;        p2 = p2->next;    }    //合并    while(p1 != NULL && p2 != NULL) {        if(p1->data <= p2->data) {            p->next = p1;            p1 = p1->next;        }else{            p->next = p2;            p2 = p2->next;        }        p = p->next;    }    //如果有一个链表为空    if(p1){        p->next = p1;    }    if(p2){        p->next = p2;    }    return root;}// (在不改变链表结构的前提下)逆序输出单链表的值void outputs(linknode *s){    if(s != NULL){          // 递归基        if(s->next != NULL){            outputs(s->next);        }    }    cout<<s->data;      // 平凡事务 }void main(){    linknode *s,*r,*h;    int k;    // 创建连接并且输出。    cout<<"输入链表长度:";    cin>>k;    s = create();    init(s,k);    // 创建链表并且输出    cout<<"输入链表长度:";    cin>>k;    r = create();    init(r,k);    //输出    pt(s);    pt(r);    //合并    h = merge(s,r);    pts(h);    // 逆输出h    cout<<"非结构改变逆输出:";    outputs(h);    cout<<endl;}