王道数据结构编程题(链式存储线性表)

文章目录

  • 1.设计一个递归算法,删除不带头结点的单链表中的所有值为x的结点。
  • 2.在带头结点的单链表中,删除所有值为x的结点,并释放其空间。
  • 3.给定一个带头结点单链表,反向输出每个结点的值。
  • 4.在带头结点的单链表中删除一个最小值结点(假设最小值结点是唯一的)。
  • 5.将带头结点的单表逆置,要求空间复杂度为 O ( n ) O(n) O(n)
  • 6.使一个带头结点的单链表所有元素递增有序。
  • 7.设在一个带表头结点的单链表中所有元素结点的数据值无序,删除表中所有介于给定的两个值之间的元素。
  • 8.给定两个单链表,编写算法找出两个链表的公共结点。
  • 9.给定一个带头结点的单链表,按递增次序输出各结点中的数据并释放结点所占存储空间。
  • 10.将一个带头结点单链表分解为两个带头结点单链表A和B,其中A含有原表中序号为奇数的元素,B含有序号为偶数的元素。
  • 11.将线性表 ( a 1 , b 1 , a 2 , b 2 , … , a n , b n ) (a_1, b_1, a_2, b_2, \dots, a_n, b_n) (a1,b1,a2,b2,,an,bn)就地分解为 ( a 1 , a 2 , … , a n ) (a_1, a_2, \dots, a_n) (a1,a2,,an) ( b n , … , b 2 , b 1 ) (b_n, \dots, b_2, b_1) (bn,,b2,b1)
  • 12.删除递增有序单链表中的重复元素。
  • 13.将两个递增有序的单链表归并为一个递减有序的单链表,除了头结点不能新建结点。
  • 14.给定两个递增有序的单链表,通过二者公共元素新建一个单链表。
  • 15.给定两个单链表,求二者元素对应集合的交集并存放在第一个单链表中。
  • 16.给定两个单链表,判断其中一个单链表是否是另一个的连续子序列。
  • 17.判断带头结点的循环双链表是否对称。
  • 18.给定两个循环双链表,将其中一个单链表链接到另一个单链表后面。
  • 19.给定一个带头结点循环双链表,从小到大依次输出链表中的值并将结点删除,直到链表为空。
  • 20.给定一个带表头结点的非循环双链表,每个结点除了值域和指针域,还有一个访问频度域。每次执行访问函数`Locate(L, x)`都会将频度加一,且每次访问结束Locate函数会按照频度非递增将结点排序,并将最近访问的结点放在同频次其他结点前面,实现Locate函数。
  • 21.给定一个带表头结点的单链表,查找其倒数第k个元素的值 。
  • 22.假定采用带头结点单链表保存单词,当两个单词有相同后缀时可共享存储空间,要求找出两个共享存储空间的单词的共同后缀起始位置。
  • 23.给定一个单链表,表中元素绝对值大小均小于正整数n,设计算法仅保留第一次出现的结点删除其余绝对值相等的结点。
  • 24.判断一个链表是否有环,若有环输出入口元素。
  • 25.将线性表 ( a 1 , a 2 , a 3 , … , a n − 1 , a n ) (a_1, a_2, a_3, \dots, a_{n-1}, a_n) (a1,a2,a3,,an1,an)重新排列为 ( a 1 , a n , a 2 , a n − 1 , …   ) (a_1, a_n, a_2, a_{n-1}, \dots) (a1,an,a2,an1,),要求空间复杂度为 O ( 1 ) O(1) O(1)
  • 附:list.h与list.c

在这里插入图片描述

1.设计一个递归算法,删除不带头结点的单链表中的所有值为x的结点。

输入样例:
5
1 2 3 4 5
3
5
1 8 2 8 3
8
0

输出样例:
1 2 4 5
1 2 3

#include 
#include 
#include 

typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

LinkList ListInit();
void ListTailInsert(LinkList *head, int e);
void ListDestroy(LinkList *head);
void ListShow(LinkList head);

LinkList ListDelete(LinkList *head, int x) {
    LNode *next_node = (*head)->next;

    if ((*head)->next) {
        (*head)->next = ListDelete(&((*head)->next), x);
    }
    if ((*head)->data == x) {
        free(*head);
        return next_node;
    } else {
        return *head;
    }
}

void ListDelete_(LinkList *head, int x) {
    LNode *tmp = *head;

    if (*head == NULL) {
        return;
    } else if ((*head)->data == x) {
        *head = (*head)->next;
        free(tmp);
        ListDelete_(&((*head)->next), x);
    } else {
        ListDelete_(&((*head)->next), x);
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, x;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(&L, e);
        }
        scanf("%d", &x);
        L = ListDelete(&L, x);
        /*ListDelete_(&L, x);*/
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

LinkList ListInit() {
    LinkList head = NULL;

    return head;
}

void ListTailInsert(LinkList *head, int e) {
    LNode *new_node = (LNode *) malloc(sizeof(LNode));

    new_node->data = e;
    new_node->next = NULL;
    if (!*head) {
        *head = new_node;
    } else {
        LNode *tail = *head;

        while (tail->next) {
            tail = tail->next;
        }
        tail->next = new_node;
    }
}

void ListDestroy(LinkList *head) {
    LNode *tmp;

    while (*head) {
        tmp = *head;
        *head = (*head)->next;
        free(tmp);
    }
}

void ListShow(LinkList head) {
    LNode *p = head;

    while (p) {
        printf("%d%c", p->data, (!p->next) ? 10 : 32);
        p = p->next;
    }
}

2.在带头结点的单链表中,删除所有值为x的结点,并释放其空间。

输入样例:
5
1 2 3 4 5
3
5
1 8 2 8 3
8
0

输出样例:
1 2 4 5
1 2 3

#include 
#include "list.h"

void ListDelete(LinkList head, int x) {
    LNode *p = head, *tmp;

    while (p->next) {
        if (p->next->data == x) {
            tmp = p->next;
            p->next = p->next->next;
            free(tmp);
        }
        p = p->next;
    }
}

void ListDelete_(LinkList head, int x) {
    LNode *tmp = head->next;

    if (!head->next) {
        return;
    } else if (head->next->data == x) {
        head->next = head->next->next;
        free(tmp);
        ListDelete_(head->next, x);
    } else {
        ListDelete_(head->next, x);
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, x;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        scanf("%d", &x);
        ListDelete(L, x);
        /*ListDelete_(L, x);*/
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

3.给定一个带头结点单链表,反向输出每个结点的值。

输入样例:
5
1 2 3 4 5
5
1 8 2 8 3
0

输出样例:
5 4 3 2 1
3 8 2 8 1

#include 
#include "list.h"

void ListInvertShow(LinkList head, int out) {
    if (head->next) ListInvertShow(head->next, 32);
    printf("%d%c", head->data, out);
}

void ListInvert(LinkList head) {
    LNode *cur = head->next, *tmp;

    head->next = NULL;
    while (cur) {
        tmp = cur->next;
        cur->next = head->next;
        head->next = cur;
        cur = tmp;
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        if (L) ListInvertShow(L->next, 10);
        /*ListInvert(L);
        ListShow(L);*/
        ListDestroy(&L);
    }
    return 0;
}

4.在带头结点的单链表中删除一个最小值结点(假设最小值结点是唯一的)。

输入样例:
5
1 2 3 4 5
5
2 1 4 3 6
0

输出样例:
2 3 4 5
2 4 3 6

#include 
#include "list.h"

void ListDeleteMin(LinkList head) {
    LNode *cur = head, *min_pos = head, *tmp;

    if (!head->next) return;//空链表
    while (cur->next) {
        if (cur->next->data < min_pos->next->data) {
            min_pos = cur;
        }
        cur = cur->next;
    }
    tmp = min_pos->next;
    min_pos->next = tmp->next;
    free(tmp);
}

int ListDeleteMin_(LinkList head, int min) {
    LNode *tmp;

    if (!head->next) return min;//head为倒数第一个结点 直接返回

    min = ListDeleteMin_(head->next, (head->next->data < min) ? head->next->data : min);
    if (head->next->data == min) {
        tmp = head->next;
        head->next = tmp->next;
        free(tmp);
    }
    return min;
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListDeleteMin(L);
        /*int min = ListDeleteMin_(L, INT_MAX);*/
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

5.将带头结点的单表逆置,要求空间复杂度为 O ( n ) O(n) O(n)

输入样例:
5
1 2 3 4 5
5
1 8 2 8 3
0

输出样例:
5 4 3 2 1
3 8 2 8 1

#include 
#include "list.h"

void ListInvert(LinkList head) {
    LNode *cur = head->next, *tmp;

    head->next = NULL;
    while (cur) {
        tmp = cur->next;
        cur->next = head->next;
        head->next = cur;
        cur = tmp;
    }
}

void ListInvert_(LinkList head, LNode *now) {
    LNode *tmp = now->next;//now结点的下一个结点

    if (now == head) {
        head->next = NULL;
    } else {
        now->next = head->next;
        head->next = now;
    }
    if (tmp) ListInvert_(head, tmp);
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        /*ListInvert(L);*/
        ListInvert_(L, L);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

6.使一个带头结点的单链表所有元素递增有序。

输入样例:
5
1 2 3 4 5
5
2 1 4 3 6
0

输出样例:
1 2 3 4 5
1 2 3 4 6

#include 
#include "list.h"

void ListSort(LinkList head) {
    LNode *left, *right = head->next, *l_tmp, *r_tmp;

    if (!head->next) return;

    while (right->next) {
        left = head;
        while (left->next->data < right->next->data) {
            left = left->next;
        }
        if (left != right) {
            l_tmp = left->next;
            r_tmp = right->next->next;
            left->next = right->next;
            left->next->next = l_tmp;
            right->next = r_tmp;
        } else {
            right = right->next;
        }
    }
}

void ListSort_(LinkList head) {
    if (!head->next) return;//空链表

    LNode *left, *right = head->next->next, *tmp;

    head->next->next = NULL;
    while (right) {
        left = head;
        while (left->next && left->next->data < right->data) {
            left = left->next;
        }
        tmp = right->next;
        right->next = left->next;
        left->next = right;
        right = tmp;
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
		/*ListSort(L);*/
        ListSort_(L);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

7.设在一个带表头结点的单链表中所有元素结点的数据值无序,删除表中所有介于给定的两个值之间的元素。

输入样例:
5
5 3 5 4 5
4 6
5
5 5 1 5 5
1 9
0

输出样例:
3 4
1

#include 
#include "list.h"

void ListDelete(LinkList head, int min, int max) {
    LNode *cursor = head, *tmp;

    if (!cursor) return;//empty

    while (cursor->next) {
        if (cursor->next->data > min && cursor->next->data < max) {
            /*delete*/
            tmp = cursor->next;
            cursor->next = cursor->next->next;
            free(tmp);
        } else {
            cursor = cursor->next;
        }
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, min, max;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        scanf("%d %d", &min, &max);
        ListDelete(L, min, max);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

8.给定两个单链表,编写算法找出两个链表的公共结点。

输入样例:
2 4 3
1 2
1 2 3 4
6 7 8
2 4 3
1 2
1 2 3 4
7 8 9
0 0 0

输出样例:
6
7

#include 
#include "list.h"

int ListFind(LinkList head_a, LinkList head_b) {
    int len_a = 0, len_b = 0;
    LNode *cur_a = head_a, *cur_b = head_b;
    /*get length*/
    while (cur_a) {
        len_a++;
        cur_a = cur_a->next;
    }
    while (cur_b) {
        len_b++;
        cur_b = cur_b->next;
    }
    
    cur_a = head_a;
    cur_b = head_b;
    if (len_a > len_b) {
        for (int i = 0; i < len_a - len_b; i++) cur_a = cur_a->next;
    } else {
        for (int i = 0; i < len_b - len_a; i++) cur_b = cur_b->next;
    }
    while (cur_a->data != cur_b->data) {
        cur_a = cur_a->next;
        cur_b = cur_b->next;
    }
    return cur_a->data;
}

void ListLink(LinkList A, LinkList B, LinkList *C);

void ListFree(LinkList *A, LinkList *B, int node_a);

int main() {
    int len_a, len_b, len_c;

    while (scanf("%d %d %d", &len_a, &len_b, &len_c)) {
        if (len_a == 0 || len_b == 0 || len_c == 0) break;

        LinkList A = ListInit();
        LinkList B = ListInit();
        LinkList C = ListInit();
        int e, node_a = len_a + 1;

        while (len_a--) {
            scanf("%d", &e);
            ListTailInsert(A, e);
        }
        while (len_b--) {
            scanf("%d", &e);
            ListTailInsert(B, e);
        }
        while (len_c--) {
            scanf("%d", &e);
            ListTailInsert(C, e);
        }
        ListLink(A, B, &C);
        printf("%d\n", ListFind(A, B));
        ListFree(&A, &B, node_a);
    }
    return 0;
}

void ListLink(LinkList A, LinkList B, LinkList *C) {
    LNode *tail_a = A, *tail_b = B;

    while (tail_a->next) tail_a = tail_a->next;
    tail_a->next = (*C)->next;//link A and C
    while (tail_b->next) tail_b = tail_b->next;
    tail_b->next = (*C)->next;//link B and C
    free(*C);//free the head of C
    *C = NULL;
}

void ListFree(LinkList *A, LinkList *B, int node_a) {
    LNode *tmp;

    while (*B) {
        tmp = *B;
        *B = (*B)->next;
        free(tmp);
    }
    while (node_a--) {
        tmp = *A;
        *A = (*A)->next;
        free(tmp);
    }
}

9.给定一个带头结点的单链表,按递增次序输出各结点中的数据并释放结点所占存储空间。

输入样例:
3
1 2 3
5
6 9 4 0 1
0

输出样例:
1 2 3
0 1 4 6 9

#include 
#include "list.h"

void ListShowFree(LinkList head) {
    LNode *cursor, *min, *tmp;

    while (head->next) {
        cursor = min = head;
        while (cursor->next) {
            if (cursor->next->data < min->next->data) min = cursor;
            cursor = cursor->next;
        }
        printf("%d%c", min->next->data, (head == min && min->next->next == NULL) ? 10 : 32);
        /*delete node min->next*/
        tmp = min->next;
        min->next = tmp->next;
        free(tmp);
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListShowFree(L);
    }
    return 0;
}

10.将一个带头结点单链表分解为两个带头结点单链表A和B,其中A含有原表中序号为奇数的元素,B含有序号为偶数的元素。

输入样例:
5
1 2 3 4 5
5
1 2 1 2 1
0

输出样例:
1 3 5
2 4
1 1 1
2 2

#include 
#include "list.h"

void ListDisconnect(LinkList L, LinkList A, LinkList B) {
    LNode *tail_a = A, *tail_b = B;

    while (L->next) {
        /*insert into list A*/
        tail_a->next = L->next;
        L->next = L->next->next;
        tail_a->next->next = NULL;
        tail_a = tail_a->next;

        if (!L->next) break;
        /*insert into list B*/
        tail_b->next = L->next;
        L->next = L->next->next;
        tail_b->next->next = NULL;
        tail_b = tail_b->next;
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListDisconnect(L, A, B);
        ListShow(A);
        ListShow(B);
        ListDestroy(&L);
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

11.将线性表 ( a 1 , b 1 , a 2 , b 2 , … , a n , b n ) (a_1, b_1, a_2, b_2, \dots, a_n, b_n) (a1,b1,a2,b2,,an,bn)就地分解为 ( a 1 , a 2 , … , a n ) (a_1, a_2, \dots, a_n) (a1,a2,,an) ( b n , … , b 2 , b 1 ) (b_n, \dots, b_2, b_1) (bn,,b2,b1)

输入样例:
5
1 2 3 4 5
0

输出样例:
1 3 5
4 2

#include 
#include "list.h"

void ListDisconnect(LinkList L, LinkList A, LinkList B) {
    LNode *tail_a = A, *tmp;

    while (L->next) {
        /*tail insert*/
        tail_a->next = L->next;
        L->next = L->next->next;
        tail_a = tail_a->next;
        tail_a->next = NULL;

        if (!L->next) break;
        /*head insert*/
        tmp = L->next->next;
        L->next->next = B->next;
        B->next = L->next;
        L->next = tmp;
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListDisconnect(L, A, B);
        ListShow(A);
        ListShow(B);
        ListDestroy(&L);
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

12.删除递增有序单链表中的重复元素。

输入样例:
5
1 2 2 2 3
5
1 1 2 3 3
0

输出样例:
1 2 3
1 2 3

#include 
#include "list.h"

void ListDelete(LinkList L) {
    LNode *left = L, *right = L->next, *tmp;

    if (!right) return;

    while (right->next) {
        if (left->next->data == right->next->data) {
            tmp = right->next;
            right->next = right->next->next;
            free(tmp);
        } else {
            left = left->next;
            right = right->next;
        }
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListDelete(L);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

13.将两个递增有序的单链表归并为一个递减有序的单链表,除了头结点不能新建结点。

输入样例:
3 3
1 3 5
2 4 6
0 0

输出样例:
6 5 4 3 2 1

#include 
#include "list.h"

void ListMerge(LinkList L, LinkList A, LinkList B) {
    LNode *tmp;

    while (A->next && B->next) {
        if (A->next->data < B->next->data) {
            tmp = A->next->next;
            A->next->next = L->next;
            L->next = A->next;
            A->next = tmp;
        } else {
            tmp = B->next->next;
            B->next->next = L->next;
            L->next = B->next;
            B->next = tmp;
        }
    }

    while (A->next) {
        tmp = A->next->next;
        A->next->next = L->next;
        L->next = A->next;
        A->next = tmp;
    }

    while (B->next) {
        tmp = B->next->next;
        B->next->next = L->next;
        L->next = B->next;
        B->next = tmp;
    }
}

int main() {
    int m, n;

    while (scanf("%d %d", &m, &n) && m != 0 && n != 0) {
        LinkList L = ListInit();
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(A, e);
        }
        while (n--) {
            scanf("%d", &e);
            ListTailInsert(B, e);
        }
        ListMerge(L, A, B);
        ListShow(L);
        ListDestroy(&L);
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

14.给定两个递增有序的单链表,通过二者公共元素新建一个单链表。

输入样例:
5 5
1 2 3 4 5
1 3 5 7 9
0 0

输出样例:
1 3 5

#include 
#include "list.h"

void ListCreat(LinkList L, LinkList A, LinkList B) {
    LNode *cur_a = A->next, *cur_b = B->next;

    while (cur_a && cur_b) {
        if (cur_a->data < cur_b->data) {
            cur_a = cur_a->next;
        } else if (cur_a->data > cur_b->data) {
            cur_b = cur_b->next;
        } else {
            ListTailInsert(L, cur_a->data);
            cur_a = cur_a->next;
            cur_b = cur_b->next;
        }
    }
}

int main() {
    int m, n;

    while (scanf("%d %d", &m, &n) && m != 0 && n != 0) {
        LinkList L = ListInit();
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(A, e);
        }
        while (n--) {
            scanf("%d", &e);
            ListTailInsert(B, e);
        }
        ListCreat(L, A, B);
        ListShow(L);
        ListDestroy(&L);
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

15.给定两个单链表,求二者元素对应集合的交集并存放在第一个单链表中。

输入样例:
5 5
1 3 5 7 9
5 6 4 3 1
0 0

输出样例:
1 3 5

#include 
#include "list.h"

void ListIntersection(LinkList A, LinkList B) {
    LNode *cur_a = A, *cur_b, *tmp;

    while (cur_a->next) {
        cur_b = B->next;
        while (cur_b) {
            if (cur_b->data == cur_a->next->data) break;
            cur_b = cur_b->next;
        }
        if (!cur_b) {
            /*cur_a->next->data doesn't appear in B*/
            tmp = cur_a->next;
            cur_a->next = cur_a->next->next;
            free(tmp);
        } else {
            cur_a = cur_a->next;
        }
    }
}

int main() {
    int m, n;

    while (scanf("%d %d", &m, &n) && m != 0 && n != 0) {
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(A, e);
        }
        while (n--) {
            scanf("%d", &e);
            ListTailInsert(B, e);
        }
        ListIntersection(A, B);
        ListShow(A);
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

16.给定两个单链表,判断其中一个单链表是否是另一个的连续子序列。

输入样例:
5 2
1 3 3 4 5
3 4
5 2
1 3 3 4 5
3 5
0 0

输出样例:
YES
NO

#include 
#include 
#include "list.h"

bool IsSub(LinkList A, LinkList B) {
    LNode *cur_a = A->next, *cur_b, *tmp;

    while (cur_a) {
        tmp = cur_a;
        cur_b = B->next;
        while (cur_b && tmp) {
            if (tmp->data == cur_b->data) {
                tmp = tmp->next;
                cur_b = cur_b->next;
            }
            else {
                break;
            }
        }
        if (!cur_b) return true;
        cur_a = cur_a->next;
    }
    return false;
}

int main() {
    int m, n;

    while (scanf("%d %d", &m, &n) && m != 0 && n != 0) {
        LinkList A = ListInit();
        LinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(A, e);
        }
        while (n--) {
            scanf("%d", &e);
            ListTailInsert(B, e);
        }
        printf("%s\n", IsSub(A, B) ? "YES" : "NO");
        ListDestroy(&A);
        ListDestroy(&B);
    }
    return 0;
}

17.判断带头结点的循环双链表是否对称。

输入样例:
5
1 2 3 2 1
5
1 2 3 4 5
0

输出样例:
YES
NO

#include 
#include 
#include 

typedef struct DLNode {
    int data;
    struct DLNode *left, *right;
} DLNode, *DLinkList;

DLinkList ListInit();
void ListRightInsert(DLinkList L, int e);
void ListDestroy(DLinkList *L);
void ListShow(DLinkList L);

bool IsSymmetric(DLinkList L) {
    DLNode *r_cur = L->right, *l_cur = L->left;

    while (r_cur != L && l_cur != L) {
        if (r_cur -> data == l_cur->data) {
            r_cur = r_cur->right;
            l_cur = l_cur->left;
        } else {
            break;
        }
    }
    return (r_cur == L && l_cur == L);
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        DLinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListRightInsert(L, e);
        }
        printf("%s\n", IsSymmetric(L) ? "YES" : "NO");
        ListDestroy(&L);
    }
    return 0;
}

DLinkList ListInit() {
    DLinkList L = (DLinkList) malloc(sizeof(DLNode));

    L->data = 0;
    L->left = L->right = L;
    return L;
}

void ListRightInsert(DLinkList L, int e) {
    DLNode *new_node = (DLNode *) malloc(sizeof(DLNode));
    DLNode *tail = L;

    while (tail->right != L) tail = tail->right;
    tail->right = L->left = new_node;
    new_node->data = e;
    new_node->left = tail;
    new_node->right = L;
}

void ListDestroy(DLinkList *L) {
    DLNode *tmp;

    while ((*L)->right != *L) {
        tmp = (*L)->right;
        (*L)->right = tmp->right;
        tmp->right->left = *L;
        free(tmp);
    }
}

void ListShow(DLinkList L) {
    DLNode *cursor = L->right;

    while (cursor != L) {
        printf("%d%c", cursor->data, (cursor->right == L) ? 10 : 32);
        cursor = cursor->right;
    }
}

18.给定两个循环双链表,将其中一个单链表链接到另一个单链表后面。

输入样例:
3 3
1 2 3
4 5 6
0 0

输出样例:
1 2 3 4 5 6

#include 
#include 
#include 

typedef struct DLNode {
    int data;
    struct DLNode *left, *right;
} DLNode, *DLinkList;

DLinkList ListInit();
void ListRightInsert(DLinkList L, int e);
void ListDestroy(DLinkList *L);
void ListShow(DLinkList L);

bool ListLink(DLinkList A, DLinkList *B) {
    DLNode *tail_a = A, *tail_b = *B;

    while (tail_a->right != A) tail_a = tail_a->right;
    while (tail_b->right != *B) tail_b = tail_b->right;
    tail_a->right = (*B)->right;
    tail_b->right = A;
    A->left = tail_b;
    (*B)->left = tail_a;
    *B = NULL;
}

int main() {
    int m, n;

    while (scanf("%d %d", &m, &n) && m != 0 && n != 0) {
        DLinkList A = ListInit();
        DLinkList B = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListRightInsert(A, e);
        }
        while (n--) {
            scanf("%d", &e);
            ListRightInsert(B, e);
        }
        ListLink(A, &B);
        ListShow(A);
        ListDestroy(&A);
    }
    return 0;
}

DLinkList ListInit() {
    DLinkList L = (DLinkList) malloc(sizeof(DLNode));

    L->data = 0;
    L->left = L->right = L;
    return L;
}

void ListRightInsert(DLinkList L, int e) {
    DLNode *new_node = (DLNode *) malloc(sizeof(DLNode));
    DLNode *tail = L;

    while (tail->right != L) tail = tail->right;
    tail->right = L->left = new_node;
    new_node->data = e;
    new_node->left = tail;
    new_node->right = L;
}

void ListDestroy(DLinkList *L) {
    DLNode *tmp;

    while ((*L)->right != *L) {
        tmp = (*L)->right;
        (*L)->right = tmp->right;
        tmp->right->left = *L;
        free(tmp);
    }
}

void ListShow(DLinkList L) {
    DLNode *cursor = L->right;

    while (cursor != L) {
        printf("%d%c", cursor->data, (cursor->right == L) ? 10 : 32);
        cursor = cursor->right;
    }
}

19.给定一个带头结点循环双链表,从小到大依次输出链表中的值并将结点删除,直到链表为空。

输入样例:
5
1 4 3 2 5
0

输出样例:
1 2 3 4 5

#include 
#include 
#include 

typedef struct DLNode {
    int data;
    struct DLNode *left, *right;
} DLNode, *DLinkList;

DLinkList ListInit();
void ListRightInsert(DLinkList L, int e);
void ListDestroy(DLinkList *L);
void ListShow(DLinkList L);

bool ListShowMin(DLinkList L) {
    DLNode *min = L, *cursor, *tmp;

    while (L->right != L) {
        cursor = L;
        while (cursor->right->right != L) {
            if (cursor->right->data < min->right->data) min = cursor;
            cursor = cursor->right;
        }
        printf("%d%c", min->right->data, (L->right == L) ? 10 : 32);
        tmp = min->right;
        min->right = tmp->right;
        tmp->right->left = min;
        free(tmp);
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        DLinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListRightInsert(L, e);
        }
        ListShowMin(L);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

DLinkList ListInit() {
    DLinkList L = (DLinkList) malloc(sizeof(DLNode));

    L->data = 0;
    L->left = L->right = L;
    return L;
}

void ListRightInsert(DLinkList L, int e) {
    DLNode *new_node = (DLNode *) malloc(sizeof(DLNode));
    DLNode *tail = L;

    while (tail->right != L) tail = tail->right;
    tail->right = L->left = new_node;
    new_node->data = e;
    new_node->left = tail;
    new_node->right = L;
}

void ListDestroy(DLinkList *L) {
    DLNode *tmp;

    while ((*L)->right != *L) {
        tmp = (*L)->right;
        (*L)->right = tmp->right;
        tmp->right->left = *L;
        free(tmp);
    }
}

void ListShow(DLinkList L) {
    DLNode *cursor = L->right;

    while (cursor != L) {
        printf("%d%c", cursor->data, (cursor->right == L) ? 10 : 32);
        cursor = cursor->right;
    }
}

20.给定一个带表头结点的非循环双链表,每个结点除了值域和指针域,还有一个访问频度域。每次执行访问函数Locate(L, x)都会将频度加一,且每次访问结束Locate函数会按照频度非递增将结点排序,并将最近访问的结点放在同频次其他结点前面,实现Locate函数。

输入样例(访问次序):
3
2
4
3
0


输出样例:
3 1 2 4 5
2 3 1 4 5
4 2 3 1 5
3 4 2 1 5

#include 
#include 
#include 

typedef struct DLNode {
    int data;
    int freq;
    struct DLNode *prev, *next;
} DLNode, *DLinkList;

DLinkList ListInit();
void ListTailInsert(DLinkList L, int e);
void ListDestroy(DLinkList *L);
void ListShow(DLinkList L);

bool Locate(DLinkList L, int e) {
    DLNode *cursor = L->next;

    while (cursor) {
        if (cursor->data == e) {
            cursor->freq++;
            while (cursor->freq >= cursor->prev->freq) {
                cursor->prev->next = cursor->next;
                cursor->next->prev = cursor->prev;
                cursor->prev->prev->next = cursor;
                cursor->next = cursor->prev;
                cursor->prev = cursor->prev->prev;
                cursor->next->prev = cursor;
            }
            return true;
        }
        cursor = cursor->next;
    }
    return false;
}

int main() {
    int x;
    DLinkList L = ListInit();

    ListTailInsert(L, 1);
    ListTailInsert(L, 2);
    ListTailInsert(L, 3);
    ListTailInsert(L, 4);
    ListTailInsert(L, 5);
    while (scanf("%d", &x) && x != 0) {
        Locate(L, x);
        ListShow(L);
    }
    ListDestroy(&L);
    return 0;
}

DLinkList ListInit() {
    DLinkList L = (DLinkList) malloc(sizeof(DLNode));

    L->data = L->freq = INT_MAX;
    L->prev = L->next = NULL;
    return L;
}

void ListTailInsert(DLinkList L, int e) {
    DLNode *new_node = (DLNode *) malloc(sizeof(DLNode));
    DLNode *tail = L;

    while (tail->next) tail = tail->next;
    tail->next = new_node;
    new_node->data = e;
    new_node->freq = 0;
    new_node->prev = tail;
    new_node->next = NULL;
}

void ListDestroy(DLinkList *L) {
    DLNode *tmp;

    while (*L) {
        tmp = *L;
        *L = (*L)->next;
        free(tmp);
    }
}

void ListShow(DLinkList L) {
    DLNode *cursor = L->next;

    while (cursor) {
        printf("%d%c", cursor->data, (!cursor->next) ? 10 : 32);
        cursor = cursor->next;
    }
}

21.给定一个带表头结点的单链表,查找其倒数第k个元素的值 。

输入样例:
5
1 2 3 4 5
3
5
1 2 3 4 5
6
0

输出样例:
3
error

#include 
#include 
#include "list.h"

bool ListFind(LinkList head, int k, int *num) {
    LNode *fast = head, *slow = head;

    if (k <= 0) return false;
    while (k--) {
        if (fast->next) {
            fast = fast->next;
        } else {
            return false;
        }
    }
    while (fast) {
        fast = fast->next;
        slow = slow->next;
    }
    *num = slow->data;
    return true;
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, k, num;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        scanf("%d", &k);
        if (ListFind(L, k, &num)) {
            printf("%d\n", num);
        } else {
            printf("error\n");
        };
        ListDestroy(&L);
    }
    return 0;
}

22.假定采用带头结点单链表保存单词,当两个单词有相同后缀时可共享存储空间,要求找出两个共享存储空间的单词的共同后缀起始位置。

输入样例:
4 2 3
l o a d
b e
i n g
0 0 0

输出样例:
i

#include 
#include 

typedef struct LNode {
    char data;
    struct LNode *next;
} LNode, *LinkList;

int ListFind(LinkList head_a, LinkList head_b) {
    int len_a = 0, len_b = 0;
    LNode *cur_a = head_a, *cur_b = head_b;
    /*get length*/
    while (cur_a) {
        len_a++;
        cur_a = cur_a->next;
    }
    while (cur_b) {
        len_b++;
        cur_b = cur_b->next;
    }

    cur_a = head_a;
    cur_b = head_b;
    if (len_a > len_b) {
        for (int i = 0; i < len_a - len_b; i++) cur_a = cur_a->next;
    } else {
        for (int i = 0; i < len_b - len_a; i++) cur_b = cur_b->next;
    }
    while (cur_a->data != cur_b->data) {
        cur_a = cur_a->next;
        cur_b = cur_b->next;
    }
    return cur_a->data;
}

LinkList ListInit();

void ListTailInsert(LinkList head, char e);

void ListLink(LinkList A, LinkList B, LinkList *C);

void ListFree(LinkList *A, LinkList *B, int node_a);

int main() {
    int len_a, len_b, len_c;

    while (scanf("%d %d %d", &len_a, &len_b, &len_c)) {
        if (len_a == 0 || len_b == 0 || len_c == 0) break;
        getchar();

        LinkList A = ListInit();
        LinkList B = ListInit();
        LinkList C = ListInit();
        int e, node_a = len_a + 1;

        while (len_a--) {
            scanf("%c", &e);
            getchar();
            ListTailInsert(A, e);
        }
        while (len_b--) {
            scanf("%c", &e);
            getchar();
            ListTailInsert(B, e);
        }
        while (len_c--) {
            scanf("%c", &e);
            getchar();
            ListTailInsert(C, e);
        }
        ListLink(A, B, &C);
        printf("%c\n", ListFind(A, B));
        ListFree(&A, &B, node_a);
    }
    return 0;
}

LinkList ListInit() {
    LinkList head = (LNode *) malloc(sizeof(LNode));

    head->data = 48;
    head->next = NULL;
    return head;
}

void ListTailInsert(LinkList head, char e) {
    LNode *new_node = (LNode *) malloc(sizeof(LNode));
    LNode *tail = head;

    while (tail->next) {
        tail = tail->next;
    }
    tail->next = new_node;
    new_node->data = e;
    new_node->next = NULL;
}

void ListLink(LinkList A, LinkList B, LinkList *C) {
    LNode *tail_a = A, *tail_b = B;

    while (tail_a->next) tail_a = tail_a->next;
    tail_a->next = (*C)->next;//link A and C
    while (tail_b->next) tail_b = tail_b->next;
    tail_b->next = (*C)->next;//link B and C
    free(*C);//free the head of C
    *C = NULL;
}

void ListFree(LinkList *A, LinkList *B, int node_a) {
    LNode *tmp;

    while (*B) {
        tmp = *B;
        *B = (*B)->next;
        free(tmp);
    }
    while (node_a--) {
        tmp = *A;
        *A = (*A)->next;
        free(tmp);
    }
}

23.给定一个单链表,表中元素绝对值大小均小于正整数n,设计算法仅保留第一次出现的结点删除其余绝对值相等的结点。

输入样例:
5
1 2 2 2 3
5
1 1 2 3 3
0

输出样例:
1 2 3
1 2 3

#include 
#include "list.h"

void ListDelete(LinkList head) {
    LNode *left = head->next, *right, *tmp;

    while (left) {
        right = left;
        while (right->next) {
            if (right->next->data == left->data) {
                tmp = right->next;
                right->next = right->next->next;
                free(tmp);
            } else {
                right = right->next;
            }
        }
        left = left->next;
    }
}

void ListDelete_(LinkList head, int n) {
    int *arr = (int *)calloc(n, sizeof(int));
    LNode *cursor = head, *tmp;

    while (cursor->next) {
        if (arr[cursor->next->data] == 1) {
            tmp = cursor->next;
            cursor->next = cursor->next->next;
            free(tmp);
        } else {
            arr[cursor->next->data]++;
            cursor = cursor->next;
        }
    }
    free(arr);
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, n = m;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        /*ListDelete(L);*/
        ListDelete_(L, n);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

24.判断一个链表是否有环,若有环输出入口元素。

输入样例(3表示将末尾链接到第三个元素处构成环):
5
21 22 23 24 25
3
5
21 22 23 24 25
-1
0

输出样例:
23
error

#include 
#include 
#include "list.h"

bool RingFind(LinkList head, int *begin) {
    LNode *fast = head, *slow = head;
    int len = 0;

    while (1) {
        /*slow step one*/
        slow = slow->next;
        /*fast step two*/
        fast = fast->next;
        if (!fast) return false;//no ring
        fast = fast->next;
        if (!fast) return false;//no ring
        len++;//count the length of this ring
        if (fast == slow) break;//meet
    }

    slow = fast = head;//initialize
    while (len--) fast = fast->next;
    while (fast != slow) {
        slow = slow->next;
        fast = fast->next;
    }
    *begin = slow->data;
    return true;
}

void CreateRing(LinkList head, int n);

void DestroyRing(LinkList L, int m);

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e, n, t = m, begin;

        while (t--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        scanf("%d", &n);
        if (n != -1) CreateRing(L, n);//-1 mean don't create ring
        if (RingFind(L, &begin)) {
            printf("%d\n", begin);
        } else {
            printf("error\n");
        };
        if (n != -1) DestroyRing(L, m);
        ListDestroy(&L);
    }
    return 0;
}

void CreateRing(LinkList head, int n) {
    LNode *cursor = head, *tail = head;

    while (tail->next) tail = tail->next;
    while (n--) cursor = cursor->next;
    tail->next = cursor;
}

void DestroyRing(LinkList L, int m) {
    LNode *tail = L;

    while (m--) tail = tail->next;
    tail->next = NULL;
}

25.将线性表 ( a 1 , a 2 , a 3 , … , a n − 1 , a n ) (a_1, a_2, a_3, \dots, a_{n-1}, a_n) (a1,a2,a3,,an1,an)重新排列为 ( a 1 , a n , a 2 , a n − 1 , …   ) (a_1, a_n, a_2, a_{n-1}, \dots) (a1,an,a2,an1,),要求空间复杂度为 O ( 1 ) O(1) O(1)

输出样例:
7
1 2 3 4 5 6 7
0

输出样例:
1 7 2 6 3 5 4

#include 
#include "list.h"

void ListReorder(LinkList head) {
    LNode *new_list = head, *cursor = head, *tmp;
    /*get middle position*/
    while (cursor->next) {
        new_list = new_list->next;
        cursor = cursor->next;
        if (cursor->next) cursor = cursor->next;
    }
    /*invert this new linklist*/
    cursor = new_list->next;
    new_list->next = NULL;
    while (cursor) {
        tmp = cursor->next;
        cursor->next = new_list->next;
        new_list->next = cursor;
        cursor = tmp;
    }
    /*merge*/
    cursor = new_list->next;
    new_list->next = NULL;
    new_list = cursor;
    cursor = head->next;
    while (new_list) {
        tmp = new_list->next;
        new_list->next = cursor->next;
        cursor->next = new_list;
        new_list = tmp;
        cursor = cursor->next->next;
    }
}

int main() {
    int m;

    while (scanf("%d", &m) && m != 0) {
        LinkList L = ListInit();
        int e;

        while (m--) {
            scanf("%d", &e);
            ListTailInsert(L, e);
        }
        ListReorder(L);
        ListShow(L);
        ListDestroy(&L);
    }
    return 0;
}

附:list.h与list.c

list.h

#ifndef CODE_LIST_H
#define CODE_LIST_H

#include 
#include 

typedef struct LNode {
    int data;
    struct LNode *next;
} LNode, *LinkList;

LinkList ListInit();

void ListTailInsert(LinkList head, int e);

void ListDestroy(LinkList *head);

void ListShow(LinkList head);

#endif

list.c

#include "list.h"

LinkList ListInit() {
    LinkList head = (LNode *) malloc(sizeof(LNode));

    head->data = 0;
    head->next = NULL;
    return head;
}

void ListTailInsert(LinkList head, int e) {
    LNode *new_node = (LNode *) malloc(sizeof(LNode));
    LNode *tail = head;

    while (tail->next) {
        tail = tail->next;
    }
    tail->next = new_node;
    new_node->data = e;
    new_node->next = NULL;
}

void ListDestroy(LinkList *head) {
    LNode *tmp;

    while (*head) {
        tmp = *head;
        *head = (*head)->next;
        free(tmp);
    }
}

void ListShow(LinkList head) {
    LNode *p = head->next;

    while (p) {
        printf("%d%c", p->data, (!p->next) ? 10 : 32);
        p = p->next;
    }
}

你可能感兴趣的:(数据结构与算法,后端,c语言,链表)