双链表(C语言,使用头节点)

代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
 * 使用头节点
 */ 

typedef struct node {
    int data;
    struct node *prev;
    struct node *next;
}NODE, *PNODE;

// 初始化
void init(PNODE *);
// 是否为空
bool is_empty(PNODE);
// 遍历
void traverse(PNODE);
// 头插法追加节点
bool head_add(PNODE *, int);
// 尾插法追加节点
bool rear_add(PNODE *, int);
// 求长度(不算头节点)
int len(PNODE);
// 插入节点(选择不使用PNODE *类型形参)
bool insert(PNODE, int, int);
// 删除节点(选择不使用PNODE *类型形参)
bool delete(PNODE, int, int *);
// 清空链表(不释放头节点, 同样选择不使用PNODE *类型形参)
void clear(PNODE);

// 函数中的删除操作未使用delete函数
void clear(PNODE head)
{
    PNODE q;
    printf("clear...\n");
    if (is_empty(head))
        return;

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

bool delete(PNODE head, int pos, int *pVal)
{
    PNODE p;
    int i = 0;

    printf("delete 位置%d", pos);
    if (NULL == head) {
        printf(" 失败,链表未初始化!\n");
        return false;
    }

    if (pos < 1 || pos > len(head)) {
        printf(" 失败,错误的位置\n");
        return false;
    }

    p = head;
    while (i < pos) {
        p = p->next;
        ++i;
    }

    *pVal = p->data;
    p->prev->next = p->next;
    // 如果不是尾节点
    if (p->next) {
        p->next->prev = p->prev;
    }

    printf("成功 值为 %d\n", *pVal);
    return true;
}

bool insert(PNODE head, int pos, int val)
{
    PNODE tmp, p;
    int i = 0;

    printf("insert 位置%d 值%d", pos, val);
    if (NULL == head) {
        printf(" 失败,请先初始化!\n");
        return false;
    }

    if (pos < 1 || pos > len(head)+1) {
        printf(" 失败,错误的位置\n");
        return false;
    }

    p = head;
    while (i < pos - 1) {
        p = p->next;
        ++i;
    }

    tmp = (PNODE)malloc(sizeof(NODE));
    tmp->data = val;
    tmp->prev = p;
    tmp->next = p->next;
    p->next = tmp;

    printf(" 成功\n");
    return true;
}

int len(PNODE head)
{
    int i = 0;
    if (is_empty(head))
        return 0;

    while (head->next) {
        head = head->next;
        ++i;    
    }
    return i;
}

bool rear_add(PNODE *pHead, int val)
{
    printf("rear_add %d", val);
    PNODE tmp, rear;

    if (*pHead == NULL) {
        printf(" 插入失败请先初始化!\n");
        return false;
    }

    // 找尾节点
    rear = *pHead;
    while (rear->next) {
        rear = rear->next;
    }

    tmp = (PNODE)malloc(sizeof(NODE));
    tmp->data = val;
    tmp->prev = rear;
    tmp->next = NULL;
    rear->next = tmp;

    printf(" 插入成功\n");
    return true;
}

bool head_add(PNODE *pHead, int val)
{
    printf("head_add %d", val);
    PNODE tmp;

    if (*pHead == NULL) {
        printf(" 插入失败请先初始化!\n");
        return false;
    }
    tmp = (PNODE)malloc(sizeof(NODE));
    tmp->data = val;
    tmp->prev = *pHead;
    tmp->next = (*pHead)->next;
    (*pHead)->next = tmp;

    printf(" 插入成功\n");
    return true;
}

void traverse(PNODE head)
{
    if (is_empty(head)) {
        printf("链表为空!\n");
        return;
    }

    PNODE p;
    p = head->next;

    while (p) {
        printf("%d ", p->data);
        p = p->next; 
    }
    putchar('\n');
}

// 未初始化或头节点next指向NULL时,都返回true
bool is_empty(PNODE head)
{
    if (! head || ! head->next)
        return true;
    return false;
}
void init(PNODE *pHead)
{
    int val;
    PNODE head, tmp, rear;
    head = (PNODE)malloc(sizeof(NODE));
    if (! head) {
        printf("malloc error\n");
        return;
    }
    // head node not asign data
    head->prev = NULL;
    head->next = NULL;
    rear = head;

    printf("请输入双向链表节点数据(0为终止输入):\n");
    while (1) {
        scanf("%d", &val);
        if (val == 0)
            break;

        tmp = (PNODE)malloc(sizeof(NODE));
        if (! tmp) {
            printf("malloc error\n");
            return;
        }

        tmp->data = val;
        tmp->prev = rear;
        tmp->next = NULL;
        rear->next = tmp;
        rear = tmp;
    }

    *pHead = head;
}

int main(void)
{
    PNODE head = NULL;
    int val;

    head_add(&head, 14);
    init(&head);
    traverse(head);
    head_add(&head, 13);
    head_add(&head, 12);
    head_add(&head, 11);
    traverse(head);

    rear_add(&head, 31);
    rear_add(&head, 32);
    rear_add(&head, 33);
    traverse(head);
    printf("长度为:%d\n", len(head));

    insert(head, 0, 100);
    insert(head, 50, 100);
    insert(head, 1, 10);
    insert(head, 1, 9);
    traverse(head);

    delete(head, 0, &val);
    delete(head, 50, &val);
    printf("长度为:%d\n", len(head));
    delete(head, 1, &val);
    traverse(head);
    delete(head, 3, &val);
    traverse(head);
    delete(head, 7, &val);
    traverse(head);
    clear(head);
    traverse(head);

    return 0;
}

output

[root@8be225462e66 c]# gcc doubly_linklist.c && ./a.out
head_add 14 插入失败请先初始化!
请输入双向链表节点数据(0为终止输入):
21
22
23
0
21 22 23
head_add 13 插入成功
head_add 12 插入成功
head_add 11 插入成功
11 12 13 21 22 23
rear_add 31 插入成功
rear_add 32 插入成功
rear_add 33 插入成功
11 12 13 21 22 23 31 32 33
长度为:9
insert 位置0 值100 失败,错误的位置
insert 位置50 值100 失败,错误的位置
insert 位置1 值10 成功
insert 位置1 值9 成功
9 10 11 12 13 21 22 23 31 32 33
delete 位置0 失败,错误的位置
delete 位置50 失败,错误的位置
长度为:11
delete 位置1成功 值为 9
10 11 12 13 21 22 23 31 32 33
delete 位置3成功 值为 12
13 21 22 23 31 32 33
delete 位置7成功 值为 33
13 21 22 23 31 32
clear...
链表为空!
[root@8be225462e66 c]#
上一篇:栈和队列


下一篇:队列的链式表示和实现(C语言)