C语言实现数据机构链表的基本操作(从键盘输入)

 

利用头插法能重新建立带头节点的新链表,即逆置

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

算法思想:逆置链表初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。

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;    //头指针后移
    }
}

接下来,进行图解:

刚开始是这样

循环前的操作,p指向首结点(即第一个结点),头结点的指针置空

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

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

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


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

q和p继续后移

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

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

 直到链表为空

链表完整代码:

#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结点指针指向第i个结点
    p->next = s;    //p指针指向s结点
    return OK;
}

Status ScanfList(LinkList &L)    //键盘输入
{
    printf("输入整数,以0结束:\n");
    ElemType e;
    int i = 1;
    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暂存被删结点ai的地址
    p->next = q->next;    //p指针(也即是第i-1个结点的指针)指向第i+1个结点
    e = q->data;    //ai结点的数据赋值给e返回
    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 i = 1;
    LinkList p = L;
    while (p->next != NULL)
    {
        p = p->next;
        if (p->data == e)return i;
            i++;
    }
    return i;
}

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;
    if (p == NULL) printf("NULL\n");
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

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 ClearList(LinkList &L)    //清空
{
    LinkList p = L->next, q;
    if (p == NULL) return OK;
    while (p != NULL)
    {
        q = p->next;
        free(p);
        p = q;
    }
    L->next = NULL;
    return OK;
}

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\n");
    ScanfList(L);
    PrnList(L);

    int k;
    printf("\n1.插入\n2:删除\n3:取值\n4:定位\n5:直接前驱\n");
    printf("6.求长度\n7:遍历\n8:逆置\n9:清空\n10:销毁\n\n0.退出\n");
    scanf("%d", &k);
    while (k != 0)
    {
        switch (k)
        {
        case 1:
            printf("在第几个位置插入何数:");
            scanf("%d%d", &i, &e);
            if (ListInsert(L, i, e)) printf("OK\n");
            break;
        case 2:
            printf("删除第几个数:");
            scanf("%d", &i);
            if (ListDelete(L, i, e))printf("删除数为:%d\n", e);
            break;
        case 3:
            printf("获取第几个数:");
            scanf("%d", &i);
            if (GetElem(L, i, e)) printf("数为:%d\n", e);
            break;
        case 4:
            printf("定位何数:");
            scanf("%d", &e);
            if (LocateElem(L, e)) printf("位序为:%d\n", LocateElem(L, e));
            break;
        case 5:
            printf("寻找何数直接前驱:");
            scanf("%d", &e);
            if (PriorElem(L, e, e1)) printf("前驱为:%d\n", e1);
            break;
        case 6:
            printf("表长为:");
            printf("%d\n", GetLength(L));
            break;
        case 7:
            printf("遍历:\n");
            PrnList(L);
            break;
        case 8:
            NiList(L);
            PrnList(L);
            printf("逆置成功\n");
            break;
        case 9:
            if (ClearList(L))printf("清空成功\n");
            break;
        case 10:
            if (Destroy(L))printf("销毁成功\n");
            break;
        default:
            printf("ERROR\n");
        }
        scanf("%d", &k);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Luoters/p/12020893.html