QT-C语言结构体建立单链表

QT项目新建

新建文件:
我们现在学习,一般新建项目用应用中的第二个选项,控制台应用。
如图,选第二个打开后,有代码

1 #include <QCoreApplication>
2
3 int main(int argc, char *argv[])
4 {
5    QCoreApplication a(argc, argv);
6
7    return a.exec();
8 }
9

什么是结构体

复习一下,什么是结构体

结构体

结构体内部的元素,即组成部分,我们一般称为“成员”。
结构体一般定义形式为:

1 struct 结构体名{
2
3	类型名1 成员名1;
4
5	类型名2 成员名2;
6
7	……
8
9	类型名n 成员名n;
10
11};

struct是关键字,是结构体类型的标志。

定义结构体变量

下面是定义结构体变量stu的三种方法

1 struct student{
2 	char *name;
3 	int score;
4 };
5
6 struct student stu
1 struct student{
2 	char *name;
3 	int score;
4 }stu;
1 struct {
2 	char *name;
3 	int score;
4 }stu;

注:

  1. 不允许对结构体本身递归定义
  2. 结构体内可以包含别的结构体
  3. 定义结构体类型,并没有给其分配空间。只有当定义结构体变量时才会分配空间给该变量
  4. 结构体变量占用空间是其成员内存和,成员按自定义顺序依次排列
  5. 初始化结构体数据时只能再定义变量的同时进行初始化赋值(各成员的初值,按顺序的放在大括号中,并用逗号分隔(如{“a”,1},{“b”,2}),一一赋值)

指向结构体的指针

  • 每个结构体变量都有自己的储存空间和地址,因此指针也可指向结构体变量
  • 结构体指针变量的定义形式:struct 结构体名称 *指针变量名
    (如:struct Student *p;p=&stu;)
  • 访问方式:
  1. 结构体变量名.成员名(stu.name,stu.age)
  2. (*指针变量名).成员名((*p).name,(*p).age)
  3. 指针变量名->成员名(p->name,p->age)

可以看到:
结构体声明如何内存的分布,
结构体指针声明结构体的首地址,
结构体成员声明该成员在结构体中的偏移地址。

链式存储和运算

链表是由一个个结点构成的,结点定义如下:

struct LinkList 
{ DataType data;//DataType自己定,定义结点数据域
 struct LinkList *next; //定义结点指针域
 };

节点,前面数据域,后面指针域
有三个函数用来处理链表相关的问题:
malloc 来动态的分配存储空间;
free 动态回收存储空间;注意:释放后数据可能存在并且维持原来的值,也可能被清空,或者被被其他的分配了,已经修改为其他值,释放只是这部分被占用的内存其他可用;不建议再使用,会出现错误,比如无限输出。
sizeof 测算某种结构所需存储空间的大小。

p = malloc(sizeof(struct LinkList)); //动态分配存储空间,返回该空间的首地址 
free(p); //动态释放指针p所指向的存储空间

单链表的建立

链表是动态存储结构,要从空表开始建立,每读入一个数据元素则动态申请一个结点,将之插在链表中合适的位置。而对 于新表的生成,一般将它插入到表尾。如下图所示即为单链表{a1,a2,a3,a4,a5} 的建立过程。初始时链首指针 H=nullptr;辅助的指针变量为 p。在这里插入图片描述
如上图,H头节点的next域开始时为空,来了一个新节点p时,先将H->next移入p->next,现在新节点的指针域为空,即p->next = H->next,可以知道,H->next是指针域,存储地址,要将新节点和头节点衔接,就可以将新节点的地址赋值给头节点,即H->next = p,;接下来,再有新节点加入,类似的,将p->next = H->next,H->next = p,循环,终止。这个过程就是将新节点的地址赋值为空(之前头结点的指针域),再将头结点的地址赋值为新节点。上述讲的是头插法,头插法产生的链表顺序与输入顺序时相反的。下面函数将用尾插法建立函数。
主函数

//主函数
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int deldate;
    Linklist *h = nullptr;            //定义链首指针为空
    h = creatlist();                  //建立单向链表
    outputlist(h);                    //输出链表
    printf("请输入要删除的数字:");     //删除指定结点
    scanf("%d",&deldate);
    if(deldate != 0)
    {
        h = delnode(h,deldate);
        outputlist(h);
    }
    return a.exec();
}

建立单链表

//建立单向链表
1 Linklist *creatlist(void)
2 {
3    Linklist *h, *p, *q;                            //定义头节点,和普通节点,尾部节点;
4    printf("当输入0时,停止建立链表\n");
5    printf("请输入链表:\n");
6    int i = 0;
7    p = q = (Linklist *)malloc(sizeof (Linklist));  //分配一个结点的内存
8    scanf("%d", &p->date);                          //新节点数据域输入数据,指针域设为空
9    p->next = nullptr;
10    h = nullptr;
11    while (p->date != 0)
12    {
13        i++;
14        if (i == 1)
15        {
16            h = p;                                  //头节点
17        }
18        else
19        {
20            q->next = p;                            //尾节点指针域指向新节点地址
21        }
22        q = p;                                      //移动指针q,新节点为尾节点
23        p = (Linklist *)malloc(sizeof(Linklist));
24        scanf("%d",&p->date);
25    }
26    free(p);
27    q->next = nullptr;                              //结束创建
28    return h;
29 }

输出单链表

1 void outputlist(Linklist *h)                        //建立函数防止输出链表时将链表变为零,也可以在建立中输出,不过要用一个新指针代替掉这里的h,如:Linklist *o;o = h;
2 {
3    printf("输出链表为:");
4    while (h->next != nullptr)
5    {
6        printf("%d  ", h->date);
7        h = h->next;
8    }
9    printf("%d\n",h->date);                         //输出最后一个元素
10    return;
11 }

删除指定位置结点

//删除链表指定结点
1 Linklist *delnode(Linklist *h,int a)
2 {
3    Linklist *s,*p,*q;
4    if (h == nullptr)
5        return (h);
6    if (h->date == a)
7    {
8
9        s = h->next;
10        free(h);
11        h = s;
12        return (h);
13    }
14    //查找元素a
15    s = h;
16    while((s->next != nullptr) && (s->next->date != a))
17    {
18        s = s->next;
19    }
20    q = s;
21    if (q->next == nullptr)
22    {
23 
24        printf("没有这个结点元素噢");
25        return(h);
26    }
27 
28    p = q->next;//此时s的指针域指向的数据域即为要删除的结点元素,即现在p就等于要删除的结点
29    q->next = p->next;//跳过中间的s->next后的结点p,直接指向p后一个节点,达到删除的目的
30    free(p);
31    return(h);
32 }

输出为:
无描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值