单链表的建立(源码)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

using namespace std;

typedef struct LNode{              //定义单链表结点类型
    int data;                       //数据域:每个结点存放一个数据元素
    struct LNode *next;             //指针域:指针指向下一个结点
}LNode, *LinkList;


//按位查找,返回第i个元素(带头结点)
LNode *GetElem(LinkList L, int i)     //LinkList L可以换成LNode *L
{
    if(i < 0)
        return NULL;
    LNode *p;              //指针p用来指向当前扫描到的结点
    int j = 0;
    p = L;
    while(p != NULL && j < i)
    {
        p = p->next;
        j++;
    }
    return p; //返回一个指针
}

//按值查找,找到数据域为e的结点
LNode *LocateElem(LinkList L, int e, int &place)  //用place返回位序!
{
    int i = 1;
    LNode *p = L->next;  //从第一个结点开始查找数据域为e的结点
    while(p != NULL && p->data != e)
    {
        p = p->next;
        i++;
    }
    place = i;
    return p; //返回一个指针
}


//求表的长度,头结点无数据,去除头结点
int ListLength(LinkList L)
{
    int len = 0;
    LNode *p = L;
    while(p->next != NULL)
    {
        p = p->next;
        len++;
    }
    return len - 1;  //去除头结点
}


//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
    L = (LNode *)malloc(sizeof(LNode));  //创建并分配一个头结点
    if(L == NULL)
        return false;                //内存不足,分配失败
    L->next = NULL;                      //头结点后暂时还没有结点
    return true;
}



//在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList &L, int i, int e)
{
    //以下代码等价于直接调用 LNode *p = GetElem(L, i - 1) //找到第i-1个结点,并用p指向它
    if(i < 1)
        return false;
    LNode *p;                //指针p指向当前扫描到的结点
    int j = 0;
    p = L;
    while(p != NULL && j < i - 1)      //找到插入位置的前驱结点
    {
        p = p->next;
        j++;
    }
    //以下代码等价于直接调用 return InsertNextNode(p, e);
    if(p == NULL)              //i值不合法
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}




//在第i个位置插入元素e(不带头结点)
bool ListInsert2(LinkList &L, int i, int e)
{
    if(i < 1)
        return false;
    if(i == 1)
    {
        LNode *s = (LNode *)malloc(sizeof(LNode));
        s->data = e;
        s->next = L;
        L = s;                 //头指针指向新结点
    }
    LNode *p;                //指针p指向当前扫描到的结点
    int j = 0;
    p = L;
    while(p != NULL && j < i - 1)      //找到插入位置的前驱结点
    {
        p = p->next;
        j++;
    }
    if(p == NULL)              //i值不合法
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}



//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p, int e)
{
    if(p == NULL)
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s == NULL)           //内存分配失败
        return false;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;

}



//前插操作:在p结点之前插入元素e
bool InsertPriorNode(LNode *p, int e)
{
    if(p == NULL)
        return false;
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if(s == NULL)
        return false;     //内存分配失败
    s->next = p->next;
    p->next = s;
    s->data = p->data;
    p->data = e;
    return true;
}



//(带头结点)删除表L中第i个位置的元素,并用e返回删除元素的值。
bool ListDelete(LinkList &L, int i, int &e)
{
    LNode *p = GetElem(L, i - 1); //找到第i-1个结点,并用p指向它
    if(p == NULL)
        return false;     //i值不合法
    if(p->next == NULL)
        return false;     //第i-1个结点之后已无其他结点
    LNode *q = p->next;    //定义一个指针q,指向要删除的结点
    e = q->data;
    p->next = q->next;     //将*q从链中断开
    free(q);
    return true;
}



//尾插法建立单链表
LinkList List_TailInsert(LinkList &L)
{
    int x;
    L = (LinkList)malloc(sizeof(LNode)); //建立头结点
    L->next = NULL;
    LNode *s,*r = L;
    printf("请输入插入的值:\n");                     //建立表尾指针
    scanf("%d", &x);
    while(x != 9999)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL;          //表尾指针后继置空
    return L;               //返回头结点L
}



//头插法建立单链表
LinkList List_HeadInsert(LinkList &L)
{
    LNode *s;
    int x;
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    printf("请输入插入的值:\n");
    scanf("%d", &x);
    while(x != 9999)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;
        L->next = s;
        scanf("%d", &x);
    }
    return L;
}


//删除所有值为x的结点(带头结点)
void Del_X_3(LinkList &L)
{
    int x;
    LNode *p = L->next;   //p用来遍历单链表
    LNode *q;             //q用来暂时替代p,然后将结点free
    LNode * pre = L;
    printf("请输入删除重复值:");
    scanf("%d", &x);
    while(p != NULL)
    {
        if(p->data == x)
        {
            q = p;
            pre->next = q->next;
            p = p->next;
            free(q);
        }
        else
        {
            pre = p;       //pre要一直为p的前驱
            p = p->next;
        }
    }
}


//**************************************功能函数*********************************************


//遍历输出函数
void PrintList(LinkList L)
{
    LNode *p = L->next; //跳过头结点
    if(ListLength(L))
    {
        printf("当前单链表所有元素:\n");
        while(p)
        {
            printf("%d ", p->data);
            p = p->next;
        }
        printf("\n");
    }
    else
        printf("当前单链表为空\n");
}


//插入功能函数
void Insert(LinkList &L)
{
    int place, e;
    bool flag;
    printf("请输入要插入的位置(从1开始)及元素(空格隔开):\n");
    scanf("%d %d", &place, &e);
    flag = ListInsert(L, place, e);
    if(flag)
    {
        printf("插入成功!\n");
        PrintList(L);
    }
}


//删除功能函数
void Delete(LinkList &L)
{
    int place, e;
    bool flag;
    printf("请输入要删除的位置(从1开始):\n");
    scanf("%d", &place);
    flag = ListDelete(L, place, e);
    if(flag)
    {
        printf("元素%d删除成功!\n", e);
        PrintList(L);
    }
}


//查找功能函数,调用LocateElem查找
void Search(LinkList L)
{
    int e, place;
    LNode *q;
    printf("请输入想查找的值:");
    scanf("%d", &e);
    q = LocateElem(L, e, place);
    if(q)
        printf("找到该元素!在链表的第%d个位置!\n",place);//用place返回位序!
    else
        printf("未找到该元素!\n");
}


//从尾到头输出每个结点的值
void R_Print(LinkList L)
{
    LNode *p = L->next, *r = NULL;   //r用来限制每次遍历的长度
    while(p->next != r)
    {
        p = p->next;
        if(p->next == r)
        {
            printf("%d", p->data);
            r = p;
            p = L->next;
        }
    }
    printf("%d", p->data);  //输出第一个元素(头结点之后第一个结点)
}


//删除唯一最小值结点(带头结点)
void Delete_Min(LinkList &L)
{
    LNode *p = L->next;   //p用来遍历结点,与q作大小比较
    LNode *q = p;        //q指向当前最小结点
    LNode *pre = L;      //pre始终指向q的前驱结点
    while(p->next != NULL)
    {
        if(q->data > p->next->data)
        {
            pre = p;
            q = p->next;
        }
        p = p->next;
    }
    pre->next = q->next;
    free(q);

}


//递增输出并释放空间
void Min_Delete(LinkList &L)
{
    LNode *p = L->next;
    LNode *pre = L;     //指向q的前驱结点
    LNode *q = p;       //指向最小值的结点
    while(p->next != NULL)
    {
        if(q->data > p->next->data)
        {
            q = p->next;
            pre = p;
        }
        p = p->next;
    }
    printf("%d ",q->data);
    pre->next = q->next;
    free(q);        //每次循环找到最小值结点并释放

}



//就地逆置(带头结点)
void Reverse(LinkList &L)
{
    LNode *p = L->next;  //p指向头结点后一个结点
    LNode *r;
    L->next = NULL;
    while(p)
    {
       r = p->next;
       p->next = L->next;  //p结点指向头结点的后继
       L->next = p;
       p = r;
    }
}


//删除结点元素值在(s,t)内的结点
void RangeDelete(LinkList &L)
{
    int s, t;
    LNode *p = L->next, *q;
    LNode *pre = L;
    printf("请输入(s,t)的值(空格隔开):");
    scanf("%d %d", &s, &t);
    while(p)
    {
        q = p;          //q用来暂存p结点
        p = p->next;    //趁p还未改变时将p往后移动
        if(q->data < t && q->data > s)
        {
            pre->next = q->next;
            free(q);
        }
        else
            pre = q;       //不满足条件则将pre往后移
    }
}


//递增排序(带头结点)
void Sort(LinkList &L)
{
    LNode *p = L->next;    //用来指向插入元素
    LNode *r = p->next;
    LNode *pre;
    p->next = NULL;
    p = r;
    while(p)
    {
        r = p->next;
        pre = L;        //每次循环都让pre指向头结点
        while(pre->next != NULL && pre->next->data < p->data)
            pre = pre->next;     //判断p插入的位置,并使pre指向插入位置的前驱结点
        p->next = pre->next;
        pre->next = p;
        p = r;
    }
}







void menu()
{
    printf("         \n");
    printf("1、 尾插\n");
    printf("2、 头插\n");
    printf("3、 插入\n");
    printf("4、 删除\n");
    printf("5、 删除重复元素\n");
    printf("6、 按值查找\n");
    printf("7、 输出\n");
    printf("8、 逆序输出\n");
    printf("9、 删除唯一最小值\n");
    printf("10、就地逆置\n");
    printf("11、递增排序\n");
    printf("12、删除区间值\n");
    printf("13、增序输出并释放空间\n");
    printf("0、 退出\n");
}


int main()
{

    LinkList L;              //声明一个指向单链表的指针
    int choice;
    while(1)
    {
        menu();
        printf("请输入菜单序号:\n");
        scanf("%d", &choice);
        if(choice == 0)
            break;
        switch(choice)
        {
            case 1:List_TailInsert(L);break;
            case 2:List_HeadInsert(L);break;
            case 3:Insert(L);break;
            case 4:Delete(L);break;
            case 5:Del_X_3(L);break;
            case 6:Search(L);break;
            case 7:PrintList(L);break;
            case 8:R_Print(L);break;
            case 9:Delete_Min(L);break;
            case 10:Reverse(L);break;
            case 11:Sort(L);break;
            case 12:RangeDelete(L);break;
            case 13:pjj(L);break;
            default:printf("输入错误!\n");
        }
    }
    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值