数据结构day5(双向链表)

 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

以下为双向链表增删改查

 

 

head.h

#ifndef __FF_H__
#define __FF_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char datedef[20];

/*
typedef struct
{
char name[20];
int age;
int score;
}student;
*/

typedef struct Node
{
    union // 数据域
    {
        int len;      // 头结点的数据域 (链表长度)
        datedef date; // 其他结点的数据域
    };
    struct Node *next; // 指针域
    struct Node *pre;
} *dlinklist, DLinklist;

dlinklist creat(int flag); // 创建新链表

int indel(dlinklist L, dlinklist p);             // p后删除 (中删)
int insert(dlinklist L, dlinklist p, datedef e); // p后插入 (中插)

void output(dlinklist L);   // 正向遍历
void T_output(dlinklist L); // 逆向遍历

int h_insert(dlinklist L, datedef s); // 头插
int h_del(dlinklist L);               // 头删
int r_insert(dlinklist L, datedef e); // 尾插
int r_del(dlinklist L);               // 尾删

int p_find(dlinklist L, int n);              // 查看位置元素
int p_update(dlinklist L, int n, datedef e); // 修改位置元素
int p_insert(dlinklist L, int n, datedef e); // 按位置插入
int p_del(dlinklist L, int n);               // 按位置删除

void L_free(dlinklist L); // 链表释放

#endif

fun.c

#include "head.h"

dlinklist creat(int flag) // 创建双向链表新结点
{
    dlinklist L = (dlinklist)malloc(sizeof(DLinklist));
    if (L == NULL)
    {
        return NULL;
    }
    if (flag == 1) // 头结点
    {
        L->len = 0;
    }
    else if (flag == 0) // 其他结点
    {
        strcpy(L->date, "");
    }
    L->next = NULL; // 初始化
    L->pre = NULL;
    return L;
}

int insert(dlinklist L, dlinklist p, datedef e) // p后插入 (中插)
{
    dlinklist s = creat(0);
    strcpy(s->date, e);
    s->next = p->next;
    s->pre = p;
    p->next->pre = s;
    p->next = s;
    L->len++;
    return 0;
}

int indel(dlinklist L, dlinklist p) // p后删除 (中删)
{
    dlinklist q = p->next;
    p->next = q->next;
    q->next->pre = p;
    L->len--;
    free(q);
    q = NULL;
    return 0;
}

int h_insert(dlinklist L, datedef s) // 头插
{
    if (L == NULL)
    {
        printf("头插失败\n");
        return -1;
    }
    dlinklist q = creat(0);
    if (q == NULL)
    {
        return -1;
    }
    strcpy(q->date, s);
    q->next = L->next;
    q->pre = L;
    if (q->next)
    {
        L->next->pre = q;
    }
    L->next = q;
    L->len++;
    return 0;
}

void output(dlinklist L) // 正向遍历
{
    if (L->next == NULL || L == NULL)
    {
        printf("遍历失败\n");
    }
    printf("正向遍历是:\n");
    dlinklist p = L;
    while (p->next)
    {
        p = p->next;
        printf("%s\t", p->date);
    }
    puts("");
    printf("该链表有%d个元素。\n", L->len);
}
/*
 *for(int i=0;i<p->len;i++)
 *{
 *p=p->next;
 *printf("%s\t",p->date);
 *}
 *puts("");
 */

void T_output(dlinklist L) // 逆向遍历
{
    if (L->next == NULL || L == NULL)
    {
        printf("遍历失败\n");
    }
    printf("逆向遍历是:\n");
    dlinklist p = L;
    while (p->next)
    {
        p = p->next;
    }
    while (p->pre != L)
    {
        printf("%s\t", p->date);
        p = p->pre;
    }
    printf("%s\t", p->date);
    puts("");
    printf("该链表有%d个元素。\n", L->len);
}

int r_insert(dlinklist L, datedef e) // 尾插
{
    if (L == NULL)
    {
        printf("链表不存在\n");
        return -1;
    }
    dlinklist p = creat(0);
    p = L;
    while (p->next)
    {
        p = p->next;
    }
    dlinklist s = creat(0);
    strcpy(s->date, e);
    s->pre = p;
    p->next = s;
    L->len++;
}

int h_del(dlinklist L) // 头删
{
    if (L->next == NULL || L == NULL)
    {
        printf("删除失败\n");
        return -1;
    }
    dlinklist p = L->next;
    L->next = p->next;
    if (p->next)
    {
        p->next->pre = L;
    }

    L->len--;
    free(p);
    p = NULL;
}

int r_del(dlinklist L) // 尾删
{
    if (L == NULL || L->next == NULL)
    {
        printf("操作失败\n");
        return -1;
    }
    dlinklist p = L;
    while (p->next->next)
    {
        p = p->next;
    }
    dlinklist s = p->next;
    p->next = NULL;
    free(s);
    s = NULL;
    L->len--;
}

int p_insert(dlinklist L, int n, datedef e) // 按位置插入
{

    if (L == NULL || n < 1 || n > L->len)
    {
        printf("位置不合法\n");
        return -1;
    }
    dlinklist p = L;
    for (int i = 0; i < n - 1; i++) // 找到第n-1个元素
    {
        p = p->next;
    }
    insert(L, p, e); // p后插入 (中插)
    return 0;
}

int p_find(dlinklist L, int n) // 查看位置元素
{
    if (L == NULL || n < 1 || n > L->len)
    {
        printf("位置不合法\n");
        return -1;
    }
    dlinklist p = L;
    for (int i = 0; i < n; i++)
    {
        p = p->next;
    }
    printf("你要找的第%d个元素为:%s\n", n, p->date);
    return 0;
}

int p_update(dlinklist L, int n, datedef e) // 修改
{
    if (L == NULL || n < 1 || n > L->len)
    {
        printf("位置不合法\n");
        return -1;
    }
    dlinklist p = L;
    for (int i = 0; i < n; i++)
    {
        p = p->next;
    }
    strcpy(p->date, e);
    return 0;
}

int p_del(dlinklist L, int n) // 按位置删除
{

    if (L == NULL || n < 1 || n > L->len)
    {
        printf("位置不合法\n");
        return -1;
    }
    if (L->next == L)
    {
        printf("该链表为空");
        return -1;
    }
    dlinklist p = L;
    for (int i = 0; i < n - 1; i++) // 找到第n-1个元素
    {
        p = p->next;
    }
    indel(L, p); //(中删)
    return 0;
}

/*
int e_search(dlinklist L,datedef e)         //查找元素位置
     {
     if(L==NULL||L->next==L)
          {
          return -1;
          }
       dlinklist p=L;
       int n=1;
       while(p->next!=L)
            {
            p=p->next;
            if(p->date==e)  需要进行字符串比较
              {
              return n;
              }
            n++;
            }
     if(n>L->len)
       {
       return -1;
       }
     }
*/

void L_free(dlinklist L) // 链表释放
{

    if (L == NULL)
    {
        return;
    }
    int n = L->len;
    for (int i = 0; i < n; i++)
    {
        h_del(L); // 头删
    }
    free(L);
    L = NULL;
}

main.c

 

#include "head.h"
int main(int argc, const char *argv)
{

    dlinklist L = creat(1);

    int n;
    datedef s, e;

    /*
    printf("你要头插的元素个数:");
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
    printf("你要头插的元素是:");
    scanf("%s",s);
    h_insert(L,s);       //头插
    }
    output(L);
    T_output(L);   //逆向遍历
    */

    printf("你要尾插的元素个数:");
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        printf("你要尾插的元素是:");
        scanf("%s", s);
        r_insert(L, s); // 尾插
    }
    output(L);
    T_output(L);

    /*
    h_del(L);            //头删
    output(L);


    r_del(L);                 //尾删
    output(L);
    */

    printf("你要查看第几个元素");
    scanf("%d", &n);
    p_find(L, n); // 查看位置元素

    printf("你要在哪个位置插入元素:");
    scanf("%d", &n);
    printf("你要插入的元素是:");
    scanf("%s", e);

    p_insert(L, n, e); // 按位置插入
    output(L);
    T_output(L);

    printf("你要修改第几个元素");
    scanf("%d", &n);
    printf("你要将该元素改为:");
    scanf("%s", e);
    p_update(L, n, e); // 修改位置元素
    output(L);

    printf("你要删除哪个位置的元素:");
    scanf("%d", &n);
    p_del(L, n); // 按位置删除
    output(L);
    //
    //

    L_free(L); // 链表释放
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值