C语言讲义——链表完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
    int _id;
    char s[50];
    struct Node* pre;// 指向前一个节点的地址
    struct Node* next;// 指向下一个节点的地址
};
void node_free(struct Node** q) {
    if( *q != NULL) {
        printf("free %d\n",(*q)->_id);
        free(*q);
        *q = NULL;
    }
}
void node_print(struct Node* q) {
    if (NULL == q) {
        puts("节点打印:空节点,无可打印");
        return;
    }

    printf("preview=%10d ", q->pre);
    printf("【address=%10d】 ", q);
    printf("【id=%2d】", q->_id);
    printf("next=%10d\n", q->next);
}
void chain_print(struct Node* qFirst) {
    if (qFirst == NULL) {
        puts("没有元素可以打印");
        return;
    }
    puts("----------↓↓↓打印链表------------");
    // 遍历链表
    struct Node* q;
    for(q = qFirst; q != NULL; q=q->next ) {
        node_print(q);
    }
    puts("----------↑↑↑打印链表------------");
}

/*
* 为链表追加节点(加在最后)
* 参数:头节点,需要追加的节点
* 返回值:无
*/
void chain_add(struct Node* qFirst, struct Node* qAdd) {
    // 定位到链表头
    struct Node* q = qFirst;
    // 只要后面(next)有节点,往后找;直到没有next的节点(最后一个)
    for(q; q->next!= NULL; q=q->next ) {
        //node_print(q);
    }
    // 此时定位在最后一个节点,下图1
    // 将新节点加在最后节点的后面(next)
    q->next = qAdd;// 下图2
    qAdd->pre = q;//下图3
}

/*
* 删除节点
* 参数:1.头结点 2.待删除的结点
*       因为被删除的结点需要置空,所以需要使用二级指针
* 返回值:-1 删除失败/0 删除成功
*/
int chain_remove(struct Node** qFirst, struct Node** qRemove) {
    struct Node* qPre = NULL;
    struct Node* qNext = NULL;
    struct Node* q = *qFirst;

    // 1.输入Check
    if(NULL == *qRemove) {
        puts("删无可删!");
        return -1;
    } else {
        printf("删除节点:id=%d\n", (*qRemove)->_id);
    }

    // 2.删除头结点,特殊对待
    if(*qFirst == *qRemove ) {

        if((*qFirst)->next == NULL) {
            // 就一个头结点的场合
            node_free(qFirst);
        } else { // 见下图4
            qNext = q->next;
            node_free(qFirst);
            *qFirst = qNext;
        }
        printf("---chain_remove(头结点):%d\n", *qFirst);
        return 0;
    }
    // 3.遍历链表
    for(q; q != NULL; q=q->next ) {
        if (q == *qRemove) {
            qPre = q->pre;
            qNext = q->next;

            if (qNext!=NULL) {// 见下图5
                qNext->pre = qPre;
                qPre->next= qNext;
            } else {
                // 尾节点的场合,见下图6
                qPre->next= NULL;
            }
            node_free(qRemove);
            return 0;
        }
    }
}

void chain_clear(struct Node** qFirst) {
    puts("\n----------Clear------------");

    if (qFirst == NULL) {
        puts("已经是空");
        return;
    }

    // 遍历链表
    //  不断删除第一个元素
    while(*qFirst != NULL) {
        chain_remove(qFirst,qFirst);
        printf("---chain_clear():头结点 %d\n", *qFirst);
    }

}

struct Node* chain_get(struct Node* qFirst, int index) {
    printf("---获取index = %d的节点:", index);
    int i = 0;
    // 遍历链表
    struct Node* q = qFirst;
    for(q; q!= NULL; q=q->next,i++ ) {
        if (index == i) {
            return q;
        }
    }
    return NULL;
}

/*
* 获取链表长度(即节点的个数)
* 参数:头节点
* 返回值:链表长度
*/
int chain_count(struct Node* qFirst) {
    if (qFirst == NULL) {
        // 头节点都没有,长度为0
        return 0;
    }
    int i = 0;
    // 遍历链表
    struct Node* q = qFirst;
    for(q; q != NULL; q=q->next) {
        // 顺藤摸瓜,直到最后一个节点
        i++;// 找到一个就+1
    }
    return i;
}
struct Node* node_new(int id) {
    struct Node* q = (struct Node*)malloc(sizeof(struct Node));
    memset(q, 0, sizeof(struct Node));
    q->_id = id;
    return q;
}
int g_id = 1;
struct Node* qHead = NULL;
void test0Node() {
    puts("###0节点的链表:");
    printf("count = %d\n",chain_count(NULL));
    chain_print(NULL);
}

void testAddNode() {
    puts("\n###添加一个节点:");
    struct Node* _q = node_new(g_id++);
    chain_add(qHead, _q);
    printf("count = %d\n",chain_count(qHead));
    chain_print(qHead);
}
void test3Node() {
    testAddNode();
    testAddNode();
    testAddNode();
    chain_print(qHead);
}

void testGetNode() {
    puts("输入需要get的节点的id");
    int nId;
    scanf("%d", &nId);
    getchar();

    struct Node* pGet;
    pGet = chain_get(qHead, nId);
    node_print(pGet);
}
void testRemoveNode() {
    puts("输入需要删除的节点的id");
    int nId;
    scanf("%d", &nId);
    getchar();

    struct Node* pGet;
    pGet = chain_get(qHead, nId);
    node_print(pGet);
    chain_remove(&qHead, &pGet);
}

void menu() {
    puts("***********************");
    puts("0.空链表打印");
    puts("1.添加1个节点");
    puts("3.添加3个节点");
    puts("4.获取节点");
    puts("5.打印链表");
    puts("7.删除节点");
    puts("8.清空节点");
    puts("9.清屏");
    puts("其它数字.退出");

    if (NULL== qHead) {
        qHead = node_new(g_id++);
        puts("生成头结点");
    }
    puts("***********************");
}
void testMain() {
    while(1) {
        menu();
        int nSelect = 0;
        scanf("%d", &nSelect);
        getchar();
        switch(nSelect) {
            case 0:
                test0Node();
                break;
            case 1:
                testAddNode();
                break;
            case 3:
                test3Node();
                break;
            case 4:
                testGetNode();
                break;
            case 5:
                chain_print(qHead);
                break;
            case 7:
                testRemoveNode();
                break;
            case 8:
                chain_clear(&qHead);
                break;
            case 9:
                system("cls");
                break;
            default:
                return;
        }
    }
}
int main(int argc, char** argv) {
    testMain();
    return 0;
}

转载于:https://www.cnblogs.com/tigerlion/p/11191803.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值