数据结构编程练习(单链表)


在这里插入图片描述

1.基于链表的两个递增有序序列的合并

描述:给定两个递增整数序列A和B,利用链表表示序列A和B,将A和B合并为一个递增的有序序列C,序列C不允许有重复数据。要求空间复杂度为 O ( 1 ) O(1) O(1)

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

输出样例:
1 2 3 4 5 6 7 8 9 10
1 2 5 9
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_free(LinkList L);

void list_merge(LinkList src1, LinkList src2, LinkList dest);

int main() {
    int m, n, x;
    while (scanf("%d %d", &m, &n)) {
        if (m == 0 && n == 0) {
            break;
        }
        /*初始化*/
        LinkList A = list_init(), B = list_init(), C = list_init();
        /*读取数据*/
        for (int i = 0; i < m; i++) {
            scanf("%d", &x);
            list_insert(x, A);
        }
        for (int i = 0; i < n; i++) {
            scanf("%d", &x);
            list_insert(x, B);
        }
        /*合并*/
        list_merge(A, B, C);
        /*输出结果*/
        list_show(C);
        /*释放已分配的内存*/
        list_free(A);
        list_free(B);
        list_free(C);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *p = (LNode *) malloc(sizeof(LNode));
    LNode *tail = L;

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

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (p == L->next) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_free(LinkList L) {
    LNode *p;
    while (L != NULL) {
        p = L;
        L = L->next;
        free(p);
    }
}

void list_merge(LinkList src1, LinkList src2, LinkList dest) {
    LNode *p = src1->next, *q = src2->next, *r = dest;
    while (p != NULL && q != NULL) {
        /*创建新结点*/
        LNode *t = (LNode *) malloc(sizeof(LNode));
        t->next = NULL;
        if (p->data < q->data) {
            t->data = p->data;
            p = p->next;
        } else if (p->data > q->data) {
            t->data = q->data;
            q = q->next;
        } else {
            t->data = p->data;
            p = p->next;
            q = q->next;
        }
        /*链接新结点*/
        r->next = t;
        r = t;
    }
    while (p != NULL) {
        LNode *t = (LNode *) malloc(sizeof(LNode));
        t->next = NULL;
        t->data = p->data;
        p = p->next;

        r->next = t;
        r = t;
    }
    while (q != NULL) {
        LNode *t = (LNode *) malloc(sizeof(LNode));
        t->next = NULL;
        t->data = q->data;
        q = q->next;

        r->next = t;
        r = t;
    }
}

2.基于链表的两个非递减有序序列的合并

描述:给定两个非递减的有序序列A和B,利用链表表示序列A和B,将A和B合并为一个非递增的有序序列C,序列C允许有重复的数据。要求空间复杂度为 O ( 1 ) O(1) O(1)

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

输出样例:
10 9 8 7 6 5 4 3 2 1
12 10 8 6 5 4 3 2 2 2 1
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_free(LinkList L);

void list_merge(LinkList src1, LinkList src2, LinkList dest);

int main() {
    int m, n, x;
    while (scanf("%d %d", &m, &n)) {
        if (m == 0 && n == 0) {
            break;
        }
        /*初始化链表*/
        LinkList A = list_init(), B = list_init(), C = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, A);
        }
        while (n--) {
            scanf("%d", &x);
            list_insert(x, B);
        }
        /*尾插法实现合并*/
        list_merge(A, B, C);
        /*输出数据*/
        list_show(C);
        /*释放空间*/
        list_free(A);
        list_free(B);
        list_free(C);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;
    tail->next = p;
}

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (p == L->next) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_free(LinkList L) {
    LNode *t;
    while (L != NULL) {
        t = L;
        L = L->next;
        free(t);
    }
}

void list_merge(LinkList src1, LinkList src2, LinkList dest) {
    LNode *p = src1->next, *q = src2->next, *r = dest;

    while (p != NULL && q != NULL) {
        /*创建新结点*/
        LNode *t = (LNode *) malloc(sizeof(LNode));
        if (p->data <= q->data) {
            t->data = p->data;
            p = p->next;
        } else {
            t->data = q->data;
            q = q->next;
        }
        /*头插法链接新结点*/
        t->next = r->next;
        r->next = t;
    }

    while (p != NULL) {
        LNode *t = (LNode *) malloc(sizeof(LNode));
        t->data = p->data;
        p = p->next;
        t->next = r->next;
        r->next = t;
    }
    while (q != NULL) {
        LNode *t = (LNode *) malloc(sizeof(LNode));
        t->data = q->data;
        q = q->next;
        t->next = r->next;
        r->next = t;
    }
}

3.基于链表的两个集合的交集

描述:给定两个递增的整数集合A和B,分别用链表表示A和B,求出A和B的交集,并存放在A中。要求空间复杂度为 O ( 1 ) O(1) O(1)

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

输出样例:
1 3 5
2 5
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_free(LinkList L);

void list_union(LinkList dest, LinkList src);

int main() {
    int m, n, x;
    while (scanf("%d %d", &m, &n)) {
        if (m == 0 && n == 0) {
            break;
        }
        /*链表初始化*/
        LinkList A = list_init(), B = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, A);
        }
        while (n--) {
            scanf("%d", &x);
            list_insert(x, B);
        }
        /*合并*/
        list_union(A, B);
        /*输出数据*/
        list_show(A);
        /*释放内存*/
        list_free(A);
        list_free(B);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (p == L->next) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_free(LinkList L) {
    LNode *t;
    while (L != NULL) {
        t = L;
        L = L->next;
        free(t);
    }
}

void list_union(LinkList A, LinkList B) {
    LNode *p = A->next, *q = B->next;
    LNode *prior = A;/*p结点的前驱*/

    while (p != NULL && q != NULL) {
        if (p->data > q->data) {
            q = q->next;
        } else if (p->data < q->data) {
            prior->next = p->next;
            free(p);
            p = prior->next;
        } else {
            prior = p;
            p = p->next;
            q = q->next;
        }
    }

    if (p != NULL) {
        prior->next = NULL;
        list_free(p);
    }
}

4.基于链表的两个集合差集

描述:给定两个递增的整数集合,分别用链表A和B表示,求出A和B的差集(即由仅在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。要求空间复杂度为 O ( 1 ) O(1) O(1)

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

输出样例:
7 9
2
1 6
2
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_destroy(LinkList *address_head);

int list_difference(LinkList A, LinkList B, LinkList C);

int main() {
    int m, n, x, count;
    while (scanf("%d %d", &m, &n)) {
        if (m == 0 && n == 0) {
            break;
        }
        /*初始化链表*/
        LinkList A = list_init(), B = list_init(), C = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, A);
        }
        while (n--) {
            scanf("%d", &x);
            list_insert(x, B);
        }
        /*求A-B*/
        count = list_difference(A, B, C);
        /*输出数据*/
        list_show(C);
        printf("%c%d", 10, count);
        /*释放内存*/
        list_destroy(&A);
        list_destroy(&B);
        list_destroy(&C);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->next = NULL;
    L->data = 0;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (p == L->next) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_destroy(LinkList *address_head) {
    LNode *head = *address_head, *tmp;
    *address_head = NULL;
    while (head != NULL) {
        tmp = head->next;
        free(head);
        head = tmp;
    }
}

int list_difference(LinkList A, LinkList B, LinkList C) {
    LNode *p = A->next, *q = B->next, *r = C;
    int count = 0;

    while (p != NULL && q != NULL) {
        if (p->data == q->data) {
            p = p->next;
            q = q->next;
        } else if (p->data < q->data) {
            list_insert(p->data, C);
            count++;
            p = p->next;
        } else {
            q = q->next;
        }
    }

    while (p != NULL) {
        list_insert(p->data, C);
        count++;
        p = p->next;
    }

    return count;
}

5.查找链表中的最大值

描述:利用单链表表示一个整数序列,通过一趟遍历在单链表中确定值最大的结点。

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

输出样例:
5
10
-1
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_destroy(LinkList *address_head);

int list_max(LinkList L);

int main() {
    int m, x;
    while (scanf("%d", &m)) {
        if (m == 0) {
            break;
        }
        /*初始化链表*/
        LinkList A = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, A);
        }
        /*输出最大值*/
        printf("%c%d", 10, list_max(A));
        /*销毁链表*/
        list_destroy(&A);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_destroy(LinkList *address_head) {
    LNode *head = *address_head, *tmp;
    *address_head = NULL;
    while (head != NULL) {
        tmp = head->next;
        free(head);
        head = tmp;
    }
}

int list_max(LinkList L) {
    LNode *p = L->next;
    int max = p->data;

    while (p != NULL) {
        if (p->data > max) {
            max = p->data;
        }
        p = p->next;
    }

    return max;
}

6.链表的逆转

描述:利用单链表表示一个整数序列,通过一趟遍历,将单链表中所有结点的链接方向逆转。要求空间复杂度为 O ( 1 ) O(1) O(1)

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

输出样例:
5 4 3 2 1
6 4 5 2 1 3
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_destroy(LinkList *address_head);

void list_invert(LinkList L);

int main() {
    int m, x;
    while (scanf("%d", &m)) {
        if (m == 0) {
            break;
        }
        /*链表初始化*/
        LinkList L = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, L);
        }
        /*逆置*/
        list_invert(L);
        /*输出数据*/
        list_show(L);
        /*释放内存*/
        list_destroy(&L);
    }
}

LinkList list_init() {
    LinkList L = (LNode *) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (L->next == p) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_destroy(LinkList *address_head) {
    LNode *head = *address_head, *tmp;
    *address_head = NULL;
    while (head != NULL) {
        tmp = head->next;
        free(head);
        head = tmp;
    }
}

void list_invert(LinkList L) {
    LNode *p = L->next, *t;
    L->next = NULL;
    while (p != NULL) {
        t = p->next;
        p->next = L->next;
        L->next = p;
        p = t;
    }
}

7.删除链表中满足区间值的结点

描述:利用单链表表示一个递增的整数序列,删除链表中值大于等于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同)。

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

输出样例:
1 5
2 6 8 10 12
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_show(LinkList L);

void list_destroy(LinkList *address_head);

void list_filter(int mink, int maxk, LinkList L);

int main() {
    int m, x, mink, maxk;
    while (scanf("%d", &m)) {
        if (m == 0) {
            break;
        }
        /*初始化头结点*/
        LinkList L = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, L);
        }
        scanf("%d %d", &mink, &maxk);
        /*对数据进行过滤*/
        list_filter(mink, maxk, L);
        /*输出单链表*/
        list_show(L);
        /*释放内存*/
        list_destroy(&L);
    }
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_show(LinkList L) {
    LNode *p = L->next;
    while (p != NULL) {
        printf("%c%d", (p == L->next) ? 10 : 32, p->data);
        p = p->next;
    }
}

void list_destroy(LinkList *address_head) {
    LNode *head = *address_head, *tmp;
    *address_head = NULL;
    while (head != NULL) {
        tmp = head->next;
        free(head);
        head = tmp;
    }
}

void list_filter(int mink, int maxk, LinkList L) {
    LNode *p = L->next, *prior = L;
    while (p != NULL) {
        if (p->data >= mink && p->data <= maxk) {
            prior->next = p->next;
            free(p);
            p = prior->next;
        } else {
            prior = p;
            p = p->next;
        }
    }
}

8.查找链表中倒数第k个结点

描述:利用单链表表示一个整数序列,请实现一个时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)的算法,通过一趟遍历在单链表中确定倒数第k个结点。

输入样例:
7
5 2 3 4 50 100 70
3
5
20 30 10 4 5
5
0

输出样例:
50
20
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(int e, LinkList L);

void list_destroy(LinkList *address_head);

int list_find(int loc, LinkList L);

int main() {
    int m, x, k;

    while (scanf("%d", &m)) {
        if (m == 0) {
            break;
        }
        /*初始化*/
        LinkList L = list_init();
        /*插入数据*/
        while (m--) {
            scanf("%d", &x);
            list_insert(x, L);
        }
        scanf("%d", &k);
        /*查找结点*/
        list_find(k, L);
        /*释放内存*/
        list_destroy(&L);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    return L;
}

void list_insert(int e, LinkList L) {
    LNode *tail = L;
    while (tail->next != NULL) {
        tail = tail->next;
    }

    LNode *p = (LNode *) malloc(sizeof(LNode));
    p->data = e;
    p->next = NULL;

    tail->next = p;
}

void list_destroy(LinkList *address_head) {
    LNode *head = *address_head, *tmp;
    *address_head = NULL;
    while (head != NULL) {
        tmp = head->next;
        free(head);
        head = tmp;
    }
}

int list_find(int loc, LinkList L) {
    LNode *p = L, *q = L;
    while (loc--) {
        q = q->next;
    }

    while (q != NULL) {
        p = p->next;
        q = q->next;
    }

    printf("%c%d", 10, p->data);
}

9.删除链表中倒数第k个结点

描述:利用单链表表示一个整数序列,请设计算法通过一趟遍历,删除链表中的倒数第k个结点。

输入样例:
7
5 2 3 4 50 100 70
3
5
20 30 10 4 5
5
1
1
1
0

输出样例:
5 2 3 4 100 70
30 10 4 5
empty
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_delete(LinkList L, int position);

int main() {
    int m, x, k;
    while (scanf("%d", &m) && m != 0) {
        LinkList L = list_init();

        while (m--) {
            scanf("%d", &x);
            list_insert(L, x);
        }
        scanf("%d", &k);
        list_delete(L, k);
        list_show(L);
        list_destroy(&L);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

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

void list_delete(LinkList L, int position) {
    LNode *p = L, *q = L->next;

    while (position--) {
        q = q->next;
    }
    while (q) {
        p = p->next;
        q = q->next;
    }
    q = p->next;
    p->next = q->next;
    free(q);
}

10.交换链表中相邻的两个结点

描述:利用单链表表示一个整数序列,请设计算法在空间复杂度为 O ( 1 ) O(1) O(1)的前提下,两两交换其中相邻的结点。
说明:需要进行实际的结点交换,不可以仅改变结点内部的值。

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

输出样例:
2 1 4 3
2 5 3 6 6
7 2 4 1 1
2
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_swap(LinkList L);

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

        while (m--) {
            scanf("%d", &x);
            list_insert(L, x);
        }
        list_swap(L);
        list_show(L);
        list_destroy(&L);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

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

void list_swap(LinkList L) {
    LNode *p = L, *q = p->next;

    while (q) {
        if (q->next == NULL) {
            break;//the number of remaining nodes less than 2
        }

        p->next = q->next;
        q->next = q->next->next;
        p->next->next = q;

        p = p->next->next;
        q = p->next;
    }
}

11.基于链表的简单选择排序

描述:试以单链表为存储结构,实现简单选择排序。

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

输出样例:
2 3 4 5 9
1 2 3 5 7 9
#include <stdio.h>
#include <stdlib.h>

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

void list_init(LinkList *L);

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_selection_sort(LinkList L);

int main() {
    int m, x;
    while (scanf("%d", &m) && m != 0) {
        LinkList L = NULL;
        list_init(&L);

        while (m--) {
            scanf("%d", &x);
            list_insert(L, x);
        }
        list_selection_sort(L);
        list_show(L);
        list_destroy(&L);
    }

    return 0;
}

void list_init(LinkList *L) {
    *L = (LNode *) malloc(sizeof(LNode));

    (*L)->data = 0;
    (*L)->next = NULL;
}

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

    *L = NULL;//avoid wild pointer
    while (head->next) {
        tmp = head->next;
        head->next = tmp->next;
        free(tmp);
    }
    free(head);
}

void list_show(LinkList L) {
    LNode *p = L->next;

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

void list_selection_sort(LinkList L) {
    LNode *p = L, *q, *tmp;
    LNode *min_prior_position;//min_prior_position->next->data == min_value

    while (p->next) {
        min_prior_position = p;
        q = p->next;
        /*find the minimum value*/
        while (q->next) {
            if (q->next->data < min_prior_position->next->data) {
                min_prior_position = q;
            }
            q = q->next;
        }
        /*swap*/
        if (min_prior_position != p) {
            if (p->next == min_prior_position) {//the values to be exchanged are adjacent
                p->next = min_prior_position->next;
                min_prior_position->next = min_prior_position->next->next;
                p->next->next = min_prior_position;
            } else {
                tmp = p->next->next;
                p->next->next = min_prior_position->next->next;
                min_prior_position->next->next = tmp;
                tmp = p->next;
                p->next = min_prior_position->next;
                min_prior_position->next = tmp;
            }
        }

        p = p->next;
    }
}

12.链表的分解

描述:利用单链表A表示一个非零整数序列,把A分解为两个具有相同结构的链表B和C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点。要求空间复杂度为 O ( 1 ) O(1) O(1),链表B和C均利用链表A的结点空间。

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

输出样例:
-6 -2 -3
3 1 4 8
-1 -2 -1
2 5 3 2 6
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_divide(LinkList src, LinkList positive, LinkList negative);

int main() {
    int m, x;
    while (scanf("%d", &m) && m != 0) {
        LinkList A = list_init();
        LinkList B = list_init();
        LinkList C = list_init();

        while (m--) {
            scanf("%d", &x);
            list_insert(A, x);
        }
        list_divide(A, C, B);
        list_show(B);
        list_show(C);
        list_destroy(&A);
        list_destroy(&B);
        list_destroy(&C);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

    if (L->next == NULL) {
        printf("\nempty");
    } else {
        while (p) {
            printf("%c%d", (p == L->next) ? 10 : 32, p->data);
            p = p->next;
        }
    }
}

void list_divide(LinkList src, LinkList positive, LinkList negative) {
    LNode *cursor = src->next;
    LNode *p_tail = positive, *n_tail = negative;

    while (cursor) {
        if (cursor->data > 0) {
            p_tail->next = cursor;
            p_tail = p_tail->next;
        } else {
            n_tail->next = cursor;
            n_tail = n_tail->next;
        }
        cursor = cursor->next;
    }

    src->next = NULL;
    p_tail->next = NULL;
    n_tail->next = NULL;
}

13.基于链栈的回文字符序列判断

描述:请设计一个算法判定给定的的字符序列是否为回文。

输入样例:
abba
abdba
good
0

输出样例:
YES
YES
NO
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_SIZE 100

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

LinkStack stack_init();

void stack_push(LinkStack *S, char e);

char stack_pop(LinkStack *S);

void stack_destroy(LinkStack *S);

bool is_palindrome(LinkStack *S, char *str);

int main() {
    char str[MAX_SIZE];
    while (scanf("%s", str) && str[0] != 48) {
        LinkStack S = stack_init();
        for (int i = 0; *(str + i) != 0; i++) {
            stack_push(&S, str[i]);
        }
        if (is_palindrome(&S, str)) {
            printf("\nYES");
        } else {
            printf("\nNO");
        }
        stack_destroy(&S);
    }

    return 0;
}

LinkStack stack_init() {
    LinkStack S = NULL;
    return S;
}

void stack_push(LinkStack *S, char e) {
    LNode *new_node = (LNode *)malloc(sizeof(LNode));

    new_node->data = e;
    new_node->next = *S;
    *S = new_node;
}

char stack_pop(LinkStack *S) {
    LNode *p = *S;
    int val = p->data;

    *S = p->next;
    free(p);
    return val;
}

void stack_destroy(LinkStack *S) {
    LNode *p = *S;

    while (*S) {
        *S = p->next;
        free(p);
    }
}

bool is_palindrome(LinkStack *S, char *str) {
    for (int i = 0; *(str + i) != 0; i++) {
        if (stack_pop(S) != *(str + i)) {
            return false;
        }
    }
    return true;
}

14.奇偶链表的分割

描述:给定一个单链表,把所有的奇数结点和偶数结点分别排在一起,重新链成一个新链表。请注意,这里的奇数结点和偶数结点指的是结点编号的奇偶性,而不是结点的值。
说明:空间复杂度为 O ( 1 ) O(1) O(1),时间复杂度为 O ( n ) O(n) O(n),n为链表结点总数。

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

输出样例:
1 3 5 2 4
1 6 5
15 3 2 4
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_init();

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_divide(LinkList L);

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

        while (m--) {
            scanf("%d", &x);
            list_insert(L, x);
        }
        list_divide(L);
        list_show(L);
        list_destroy(&L);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

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

void list_divide(LinkList L) {
    LNode *cursor = L->next;
    LNode *odd_tmp = (LNode *) malloc(sizeof(LNode));//fake head node
    LNode *even_tmp = (LNode *) malloc(sizeof(LNode));//fake head node
    LNode *odd_tail = odd_tmp, *even_tail = even_tmp;

    while (cursor) {
        /*handle odd nodes*/
        odd_tail->next = cursor;
        odd_tail = odd_tail->next;
        /*handle even nodes*/
        if (!cursor->next) break;
        cursor = cursor->next;
        even_tail->next = cursor;
        even_tail = even_tail->next;
        cursor = cursor->next;
    }

    /*sequence: L->odd->even*/
    L->next = odd_tmp->next;
    free(odd_tmp);
    odd_tail->next = even_tmp->next;
    free(even_tmp);
    even_tail->next = NULL;
}

15.基于链表的两数之和

利用头插法创建两个单链表,每个单链表表示一个整数,请设计算法计算出两个整数的和并储存到新的链表中。

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

输出样例:
5 7 9
6 2 1 1
0 1 0 1
#include <stdio.h>
#include <stdlib.h>

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

LinkList list_create(int len);

LinkList list_init();

void list_insert(LinkList L, int e);

void list_destroy(LinkList *L);

void list_show(LinkList L);

void list_get_sum(LinkList summand, LinkList addend, LinkList sum);

int main() {
    int m, n;
    while (scanf("%d %d", &m, &n) && !(m == 0 && n == 0)) {
        LinkList summand = list_create(m);
        LinkList addend = list_create(n);
        LinkList sum = list_init();

        list_get_sum(summand, addend, sum);
        list_show(sum);
        list_destroy(&summand);
        list_destroy(&addend);
        list_destroy(&sum);
    }

    return 0;
}

LinkList list_create(int len) {
    LinkList L = (LinkList) malloc(sizeof(LNode));
    L->data = 0;
    L->next = NULL;
    while (len--) {
        LNode *new_node = (LNode *)malloc(sizeof(LNode));
        scanf("%d", &(new_node->data));
        new_node->next = L->next;
        L->next = new_node;
    }
    return L;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

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

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

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

void list_get_sum(LinkList summand, LinkList addend, LinkList sum) {
    LNode *p = summand->next;
    LNode *q = addend->next;
    int carry_val = 0;

    while (p && q) {
        list_insert(sum, (p->data + q->data + carry_val) % 10);
        carry_val = (p->data + q->data + carry_val) / 10;
        p = p->next;
        q = q->next;
    }
    while (p) {
        list_insert(sum, (p->data + carry_val) % 10);
        carry_val = (p->data + carry_val) / 10;
        p = p->next;
    }
    while (q) {
        list_insert(sum, (q->data + carry_val) % 10);
        carry_val = (q->data + carry_val) / 10;
        q = q->next;
    }

    if (carry_val != 0) {
        list_insert(sum, carry_val);
    }
}

16.删除链表中绝对值相等的结点

描述:利用单链表表示一个整数序列,实现一个时间复杂度为 O ( n ) O(n) O(n)的算法,对于链表中绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。

输入样例:
5
21 -15 -15 -7 15
7
90 32 -90 -66 77 66 90
0

输出样例:
21 -15 -7
90 32 -66 77
#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

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

LinkList list_init();

void list_insert(LinkList L, int x);

void list_destroy(LinkList *L);

void list_show(LinkList L);

int get_absolute(int x);

void list_delete(LinkList L);

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

        while (m--) {
            scanf("%d", &x);
            list_insert(L, x);
        }
        list_delete(L);
        list_show(L);
        list_destroy(&L);
    }

    return 0;
}

LinkList list_init() {
    LinkList L = (LinkList) malloc(sizeof(LNode));

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

void list_insert(LinkList L, int x) {
    LNode *new_node = (LNode *) malloc(sizeof(LNode));
    LNode *tail = L;

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

void list_destroy(LinkList *L) {
    LNode *head = *L, *tmp;

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

void list_show(LinkList L) {
    LNode *p = L->next;

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

int get_absolute(int x) {
    return (x > 0) ? x : -x;
}

void list_delete(LinkList L) {
    LNode *p = L, *tmp;
    int count[MAX_SIZE] = {0};

    while (p->next) {
        if (count[get_absolute(p->next->data)]) {
            tmp = p->next;
            p->next = tmp->next;
            free(tmp);
        } else {
            count[get_absolute(p->next->data)]++;
            p = p->next;
        }
    }
}
  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值