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;
注:
- 不允许对结构体本身递归定义
- 结构体内可以包含别的结构体
- 定义结构体类型,并没有给其分配空间。只有当定义结构体变量时才会分配空间给该变量
- 结构体变量占用空间是其成员内存和,成员按自定义顺序依次排列
- 初始化结构体数据时只能再定义变量的同时进行初始化赋值(各成员的初值,按顺序的放在大括号中,并用逗号分隔(如{“a”,1},{“b”,2}),一一赋值)
指向结构体的指针
- 每个结构体变量都有自己的储存空间和地址,因此指针也可指向结构体变量
- 结构体指针变量的定义形式:struct 结构体名称 *指针变量名
(如:struct Student *p;p=&stu;) - 访问方式:
- 结构体变量名.成员名(stu.name,stu.age)
- (*指针变量名).成员名((*p).name,(*p).age)
- 指针变量名->成员名(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 }
输出为: