链表(三)

20.设头指针为工的带有表头结点的非循环双向链表, 其每个结点中除有pred(前驱指针).data(数据)和next(后继指针)城外, 还有一个访问频度域freq.在链表被启用前, 其值均初始化为零。每当在链表中进行一次Locate(L, x)运算时令元素值为×的结点中freq域的值增1, 并使此链表中结点保持按访问频度非增(递减)的顺序排列, 同时最近访问的结点排在频度相同的结点前面, 以便使频繁访问的结点总是靠近表头。试编写符合上述要求的LocateL, x)运算的算法, 该运算为函数过程, 返回找到结点的地址, 类型为指针型。

DLinkList Locate(DLinkList& L, ElemType x) {
    DNode* p = L->next, * q;
    while (p && p->data != x)
        p = p->next;
    if (!p) {
        printf('不存在结点为x');
        exit(0);
    }
    else {
        p->freq++;
        //断链
        if (p->next != NULL) {
            p->next->pre = p;
            p->pre->next = p->next;
        }
        q = p->pre;
        while (q != L && q->fre <= p->fre) {
            q = q->pre;
        }
        q->next->pre = p;
        p->next = q->next;
        q->next = p;
        p->pre = q;
    }
    return p;
}

21.已知一个带有表头结点的单链表,结点结构为  【data,link】。假设该链表只给出了头指针list.在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第七个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0,要求:1)描述算法的基本设计思想
2)描述算法的详细实现步骤。
3)根据设计思想和实现步骤,采用程序设计语言描述算法(使用C.C++或Java语言实现),关键之处请给出简要注释。

typedef int ElemType
typedef struct LNode {
    ElemType data;
    struct LNode* link;
}LNode,*LinkList;

int search_k(LinkList list, int k) {
    LNode* p=list->link, * q=list->link;
    int count;
    while (p != NULL) {
        if (count < k) count++;
        else q = q->link;
        p = p->link;
    }
    if(count<k)
        return 0
    else {
        printf("%d", q->data);
        return 1;
    }
}

typedef struct Node {
    char data;
    struct Node* next;
}SNode;
int listlen(SNode* head) {
    int len = 0;
    while (head->next != NULL) {
        len++;
    }
    return len;
}
SNode* find_addr(SNode* str1, SNode* str2) {
    int m, n;
    SNode* p, * q;
    m = listlen(str1);
    n = listlen(str2);
    for (p = str1; m > n; m--)
        p = p->next;
    for (q = str2; m < n; n--)
        q = q->next;
    while (p->next != NULL && p->next != q->next) {
        p = p->next;
        q = q->next;
    }
    return p->next;
}

typedef struct node {
    int data;
    struct node* link;
}Node,*PNode;

void func(Pnode h, int n) {
    PNode p = h, r;
    int* q, m;
    q = (int*)malloc(sizeof(int) * (n + 1));
    for (int i = 0; i < n + 1; i++)
        *(q + i) = 0;
    while (p->link != NULL) {
        m = p->link->data > 0 ? p->link->data : -p->link->data;
        if (*(q + m) == 0) {
            *(q + m) = 1;
            p = p->link;
        }
        else {
            r = p->link;
            p->link = r->link;
            free(r);
        }
    }
    free(q);
}

24.设计一个算法完成:判断一个链表是否有环,如果有,找出环的入口点并返回,否则返回NULL。

 

 则有2 (a+x)=atn*rtx,即a-n*r-x。显然从头结点到环的入口点的距离等于n倍的环长减去环的入口点到相遇点的距离。因此可设置两个指针,一个指向head,一个指向相遇点,两个指针同步移动(均为一次走一步),相遇点即为环的入口点。

LNode* FindLoopStart(LNode* head) {
    LNode* fast = head, * slow = head;
    while (slow != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) break;     //查找到相遇点
    }
    if (slow == NULL || fast->next == NULL)
        return NULL;
    LNode* p1 = head, * p2 = slow;
    while (p1 != p2) {
        p1 = p1->next;
        p2 = p2->next;
    }
    return p1;
}

void change_list(NODE* h) {
    NODE* p, * q, * r, * s;
    p = q = h;
    while (q->next != NULL) {
        p = p->next;
        q = q->next;
        if (q->next != NULL)q = q->next;
    }
    q = p->next;    //p中间结点
    p->next = NULL;
    while (q != NULL) {   //p看作头结点
        r = q->next;
        q->next = p->next;
        p->next = q;
        q = r;
    }
    s = h->next;
    q = p->next;
    p->next = NULL;
    while (q != NULL) {
        r = q->next;
        q->next = s->next;
        s->next = q;
        s = q->next;
        q = r;
    }
}

 

posted @ 2021-08-13 16:35  为红颜  阅读(171)  评论(0编辑  收藏  举报