zoukankan      html  css  js  c++  java
  • C语言实现数据机构链表的基本操作(从键盘输入生成链表、读取数组生成链表)

     

    利用头插法实现逆置

    下面简单介绍一下,算法思想结合图示看

    算法思想:“删除”头结点与链表其他结点的原有联系(即将头结点的指针置空),再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的头结点,如此循环,直至原链表为空。

    这是鬼话,看不懂可以不看,看下面就行......

    void NiList(LinkList &L)    //逆置
    {
        LinkList p = L->next, q;    //L->next是头结点的指针,p指针指向了首结点
        L->next = NULL;    //将头结点的指针置空
        while (p != NULL)
        {
            q = p;    //指针q从指向第一个结点开始后移
            p = p->next;    //指针p从指向第二个结点开始后移
            q->next = L->next;    //指针q所指向结点的指针q->next指向其上一个结点
            L->next = q;    //头结点的指针后移
        }
    }

    接下来,进行图解:

    刚开始是这样

    L->next是头结点指针。循环前的操作,p指向首结点(即第一个结点),头结点的指针置空

    进入循环,q和p分别指向第一个和第二个节点

    q所指向结点的指针q->next指向其(q->next)上一个结点,这里上一个结点的指针为空,故q->next也为空

    L->next = q;    //头指针后移,指向首结点
     


     进入第二轮循环,这是发生重大变化的关键时期

    q和p继续后移,这个图有点错误懒得改了,就是后移后,指针q指向了b结点,指针p指向了c结点

    q所指向结点的指针q->next指向其上一个结点

    头指针后移,指向第二个结点

    你可以看到此时已经开始逆置,如此循环, 直到p==NULL为空

    链表完整代码: 

    1):从键盘输入生成链表

    #include<stdio.h>
    #include<stdlib.h>
    #include<malloc.h>
    
    #define OK              1
    #define ERROR           0
    #define INFEASIBLE        -1
    #define OVERFLOW        -2
    #define TRUE            1
    #define FALSE            0
    
    typedef int Status;
    typedef int ElemType;
    typedef struct LNode
    {
        ElemType data;
        struct LNode* next;
    }LNode,*LinkList;
    /*定义了两种新的数据类型LNode和LinkList,显然各个结点是LNode类型的,
    头指针和结点的next成员是LinkList类型的,L是LinkList这个新的结构体指针类型定义的头指针*/
    
    Status InitList(LinkList &L)    //初始化
    {
        L = (LinkList)malloc(sizeof(LNode));
        if (L == NULL)return ERROR;
        L->next = NULL;
        return OK;
    }
    
    Status ListEmpty(LinkList L)    //判空
    {
        if (L->next == NULL) return TRUE;
        return FALSE;
    }
    
    Status ListInsert(LinkList &L, int i, ElemType e)    //插入
    {
        int j = 0;
        LinkList p = L, s;    //指针p指向头指针
        if (i<1) return ERROR;
        while ((p != NULL) && (j<i - 1))
        {
            p = p->next;
            j++;
        }
        if(p==NULL)return ERROR;
        s = (LNode*)malloc(sizeof(LNode));    //生成新节点
        if (s == NULL) return ERROR;
        s->data = e;    //s结点暂存e
        s->next = p->next;    //s结点的指针s->next指向第i个结点
        p->next = s;    //第i-1个结点的指针p->next指向s结点
        return OK;
    }
    
    Status ScanfList(LinkList &L)    //键盘输入
    {
        ElemType e;
        int i = 1;
        printf("输入整数,以0结束:
    ");
        scanf("%d", &e);
        while (e != 0)
        {
            if (!ListInsert(L, i, e)) return ERROR;
            i++;
            scanf("%d", &e);
        }
        return OK;
    }
    
    Status ListDelete(LinkList &L, int i, ElemType &e)    //删除
    {
        int j = 0;
        LinkList p = L, q;
        if ((i<1) || (L->next == NULL)) return ERROR;
        while ((p != NULL) && (j<i - 1))
        {
            p = p->next;
            j++;
        }
        if (p == NULL) return ERROR;
        q = p->next;    //指针q暂存被删结点(第i个结点)的地址
        p->next = q->next;    //指针p(即第i-1个结点的指针)指向被删结点(第i+1个结点)
        e = q->data; 
        free(q);
        return OK;
    }
    
    Status GetElem(LinkList L, int i, ElemType &e)    //取值
    {
        int j = 1;
        LinkList p = L->next;
        if (i<1) return ERROR;
        while ((p != NULL) && (j<i))
        {
            p = p->next;
            j++;
        }
        if (p == NULL) return ERROR;
        e = p->data;
        return OK;
    }
    
    int LocateElem(LinkList L, ElemType e)    //定位
    {
        int j = 1;
        LinkList p = L->next;
        while (p != NULL)
        {
            if (p->data == e)return j;
            p = p->next;
            j++;
        }
        return j;
    }
    
    Status PriorElem(LinkList L, ElemType e, ElemType &pr_e)    //直接前驱
    {
        LinkList p = L->next;
        if (p->data == e) return ERROR;    //首结点没有直接前驱
        while (p != NULL)
        {
            if (p->next->data == e) break;
            p = p->next;
        }
        if (p == NULL) return ERROR;    //指针p一直移到尾结点仍找不到e,返回错误
        pr_e = p->data;
        return OK;
    }
    
    int GetLength(LinkList L)    //求长度
    {
        int i = 0;
        LinkList p = L;
        while (p->next != NULL)
        {
            p = p->next;
            i++;
        }
        return i;
    }
    
    void PrnList(LinkList L)    //遍历
    {
        LinkList p = L->next;
        while (p != NULL)
        {
            printf("%d ", p->data);
            p = p->next;
        }
        printf("
    ");
    }
    
    void NiList(LinkList &L)    //逆置
    {
        LinkList p = L->next, q;    //p指针指向了首结点
        L->next = NULL;    //将头结点的指针置空
        while (p != NULL)
        {
            q = p;    //指针q从指向第一个结点开始后移
            p = p->next;    //指针p从指向第二个结点开始后移
            q->next = L->next;    //指针q所指向结点的指针q->next指向其上一个结点
            L->next = q;    //头结点的指针后移
        }
    }
    
    Status Destroy(LinkList &L)    //销毁,从首结点开始
    {
        LinkList p = L->next, q;
        while (p != NULL)
        {
            q = p->next;
            free(p);
            p = q;
        }
        free(L);
        return OK;
    }
    
    
    int main()
    {
        int i;
        ElemType e, e1;
    
        LinkList L;
        if (InitList(L)) printf("OK
    ");
        ScanfList(L);
        PrnList(L);
    
        int k;
        printf("
    1.插入
    2:删除
    3:取值
    4:定位
    5:直接前驱
    ");
        printf("6.求长度
    7:遍历
    8:逆置
    9:销毁
    
    0.退出
    ");
        scanf("%d", &k);
        while (k != 0)
        {
            switch (k)
            {
            case 1:
                printf("在第几个位置插入何数:");
                scanf("%d%d", &i, &e);
                if (ListInsert(L, i, e)) printf("OK
    ");
                break;
            case 2:
                printf("删除第几个数:");
                scanf("%d", &i);
                if (ListDelete(L, i, e))printf("删除数为:%d
    ", e);
                break;
            case 3:
                printf("获取第几个数:");
                scanf("%d", &i);
                if (GetElem(L, i, e)) printf("数为:%d
    ", e);
                break;
            case 4:
                printf("定位何数:");
                scanf("%d", &e);
                if (LocateElem(L, e)) printf("位序为:%d
    ", LocateElem(L, e));
                break;
            case 5:
                printf("寻找何数直接前驱:");
                scanf("%d", &e);
                if (PriorElem(L, e, e1)) printf("前驱为:%d
    ", e1);
                break;
            case 6:
                printf("表长为:");
                printf("%d
    ", GetLength(L));
                break;
            case 7:
                printf("遍历:
    ");
                PrnList(L);
                break;
            case 8:
                NiList(L);
                PrnList(L);
                printf("逆置成功
    ");
                break;
            case 9:
                if (Destroy(L))printf("销毁成功
    ");
                break;
            default:
                printf("ERROR
    ");
            }
            scanf("%d", &k);
        }
        return 0;
    }
    View Code

    2):读取数组生成链表

    #include<stdio.h>
    #include<stdlib.h>
    
    #define OK 1
    #define ERROR 0
    #define INFEASIBLE -1
    #define OVERFLOW -2
    #define TRUE 1
    #define FALSE 0
    
    typedef int Status;
    typedef int ElemType;
    typedef struct LNode{
        ElemType data;
        struct LNode *next;
    }LNode, *LinkList;
    /*定义了两种新的数据类型LNode和LinkList,显然各个结点是LNode类型的,
    头指针和结点的next成员是LinkList类型的,L是LinkList结点指针类型定义的头指针*/
    
    Status InitList(LinkList &L)    //初始化
    {
        L = (LinkList)malloc(sizeof(LNode));
        if (L == NULL)return ERROR;
        L->next = NULL;
        return OK;
    }
    
    Status ListEmpty(LinkList L)    //判空
    {
        if (L->next == NULL)return ERROR;
        else return FALSE;
    }
    
    Status ListInsert(LinkList &L, int i, ElemType e)    //插入
    {
        int j = 0;
        LinkList p = L, s;    //指针p指向头指针
        if (i < 1)return ERROR;
        while (p != NULL && j < i - 1)
        {
            p = p->next;
            j++;
        }
        if (p == NULL)return ERROR;
        s = (LNode*)malloc(sizeof(LNode));    //生成新节点
        if (s == NULL)return ERROR;
        s->data = e;    //结点s暂存e
        s->next = p->next;    //s结点的指针s->next指向第i个结点
        p->next = s;    //指针p指向s结点
        return OK;
    }
    
    Status CreateList(LinkList &L,ElemType element[], int n)    //数组生成链表
    {
        int i;
        for (i = 0; i < n; i++)
            if (!ListInsert(L, i + 1, element[i])) return ERROR;
        return OK;
    }
    
    Status ListDelete(LinkList &L, int i, ElemType &e)    //删除
    {
        int j = 0;
        LinkList p = L, q;
        if (i < 1 || p->next == NULL)return ERROR;
        while (p != NULL && j<i - 1)
        {
            p = p->next;
            j++;
        }
        if (p == NULL)return ERROR;
        q = p->next;    //指针q暂存被删结点(第i个结点)的地址,故指针q指向了被删结点
        p->next = q->next;    //指针p(即第i-1个结点的指针)指向被删结点的下一结点(第i+1个结点)
        e = q->data;
        free(q);
        return OK;
    }
    
    Status GetElem(LinkList L, int i, ElemType &e)    //取值
    {
        int j = 1;
        LinkList p = L->next;
        if (i < 1)return ERROR;
        while (p != NULL && j<i)
        {
            p = p->next;
            j++;
        }
        if (p == NULL)return ERROR;
        e = p->data;
        return OK;
    }
    
    int LocateElem(LinkList L, ElemType e)    //定位
    {
        int j = 1;
        LinkList p = L->next;
        while (p != NULL)
        {
            if (p->data == e)return j;
            p = p->next;
            j++;
        }
        return j;
    }
    
    Status PriorElem(LinkList L, ElemType e, ElemType &pr_e)    //直接前驱
    {
        LinkList p = L->next;
        if (p->data==e)return ERROR;    //首结点没有直接前驱
        while (p != NULL)
        {
            p = p->next;
            if (p->next->data == e)break;
        }
        if (p == NULL)return ERROR;    //指针p一直移到尾结点仍找不到e,返回错误
        pr_e = p->data;
        return OK;
    }
    
    int GetLength(LinkList L)    //求长度
    {
        int i = 0;
        LinkList p = L;
        while (p->next != NULL)
        {
            p = p->next;
            i++;
        }
        return i;
    }
    
    void PrnList(LinkList L)    //遍历
    {
        LinkList p = L->next;
        while (p != NULL)
        {
            printf("%d ", p->data);
            p = p->next;
        }
        printf("
    ");
    }
    
    Status NiList(LinkList &L)    //逆置
    {
        LinkList p = L->next, q;    //指针p指向了首结点
        L->next = NULL;    //将头结点指针置空
        while (p != NULL)
        {
            q = p;    //指针q从指向第一个结点开始后移
            p = p->next;    //指针p从指向第二个结点开始后移
            q->next = L->next;    //指针q所指向结点的指针q->next指向其上一个结点
            L->next = q;    //头结点的指针后移
        }
        return OK;
    }
    
    Status Destroy(LinkList &L)    //销毁,从首结点开始
    {
        LinkList p = L->next, q;
        if (p == NULL)return ERROR;
        while (p != NULL)
        {
            q = p->next;
            free(p);
            p = q;
        }
        free(L);
        return OK;
    }
    
    int main()
    {
        int i;
        ElemType e, e1;
    
        LinkList L;
        ElemType element[] = { 15, 3, 59, 27, 8, 11, 32 };
        if (InitList(L)) printf("OK
    ");
        CreateList(L,element,7);
        PrnList(L);
    
        int k;
        printf("
    1.插入
    2:删除
    3:取值
    4:定位
    5:直接前驱
    ");
        printf("6.求长度
    7:遍历
    8:逆置
    9:销毁
    
    0.退出
    ");
        scanf("%d", &k);
        while (k != 0)
        {
            switch (k)
            {
            case 1:
                printf("在第几个位置插入何数:");
                scanf("%d%d", &i, &e);
                if (ListInsert(L, i, e)) printf("OK
    ");
                break;
            case 2:
                printf("删除第几个数:");
                scanf("%d", &i);
                if (ListDelete(L, i, e))printf("删除数为:%d
    ", e);
                break;
            case 3:
                printf("获取第几个数:");
                scanf("%d", &i);
                if (GetElem(L, i, e)) printf("数为:%d
    ", e);
                break;
            case 4:
                printf("定位何数:");
                scanf("%d", &e);
                if (LocateElem(L, e)) printf("位序为:%d
    ", LocateElem(L, e));
                break;
            case 5:
                printf("寻找何数直接前驱:");
                scanf("%d", &e);
                if (PriorElem(L, e, e1)) printf("前驱为:%d
    ", e1);
                break;
            case 6:
                printf("表长为:");
                printf("%d
    ", GetLength(L));
                break;
            case 7:
                printf("遍历:
    ");
                PrnList(L);
                break;
            case 8:
                NiList(L);
                PrnList(L);
                printf("逆置成功
    ");
                break;
            case 9:
                if (Destroy(L))printf("销毁成功
    ");
                break;
            default:
                printf("ERROR
    ");
            }
            scanf("%d", &k);
        }
        return 0;
    }
    View Code
    -----------------------------------------------------转载需备注博主名和原创网址!!!------------------------------------------------------
  • 相关阅读:
    1.1 控制div属性
    1.7 节点进行排序显示
    [iOS问题归总]iPhone上传项目遇到的问题
    [iOS]iPhone进行真机测试(基础版)
    [iOS]利用Appicon and Launchimage Maker生成并配置iOSApp的图标和启动页
    [cocoapods]cocoapods问题解决
    [cocoapods] 如何卸载工程里的cocoapods
    [iOS]如何把App打包成ipa文件,然后App上架流程[利用Application Loader]
    [iOS]开发者证书和描述文件的作用
    [iOS]解决模拟器无法输入中文问题
  • 原文地址:https://www.cnblogs.com/Luoters/p/12020893.html
Copyright © 2011-2022 走看看