什么是结构体

没有学习结构体时定义两本书 并记录他们的书名以及价格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include<string.h>
int main() {
char name1[100],name2[100];
int price1,price2;

strcpy(name1,"结构体真好");
price1=250;
strcpy(name2,"结构体好棒");
price2=290;

printf("%s %d\n",name1,price1);
printf("%s %d\n",name2,price2);
return 0;
}

稍不留神就会记错对应关系

下面简单定义一个结构体来实现上述功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include<string.h>
struct Book{
char name[100];
int price;
};
int main() {
struct Book book1,book2;
strcpy(book1.name,"结构体真好");
book1.price=250;
strcpy(book2.name,"结构体好棒");
book2.price=290;

printf("%s %d\n",book1.name,book1.price);
printf("%s %d\n",book2.name,book2.price);
return 0;
}

结果
结构体真好 250
结构体好棒 290

补充:结构体数组两种定义方式

1
2
3
4
5
struct Book{
char name[100];
int price;
};
struct Book books[10];
1
2
3
4
struct Book{
char name[100];
int price;
}books[10];

但是每次定义一个结构体变量都要写一个struct好麻烦的 需要利用typedef简化一下

typedef

typedef可以自定义一个变量类型

1
2
3
4
5
6
typedef int ABC;
ABC main(){
ABC a=1;
printf("%d\n",a);
return 0;
}

结果:1

上述程序再次遇见ABC 会把他理解为int类型去处理

所以结构体也可以用其简化

typedef struct book book 然后就可以用book来表示struct book

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include<string.h>

struct book{
char name[100];
int price;
};
typedef struct book Book;
int main() {
Book books[10];
strcpy(books[0].name,"结构体真好");
books[0].price=250;
strcpy(books[1].name,"结构体好棒");
books[1].price=290;

for(int i=0;i<2;i++)
printf("%s %d\n",books[i].name,books[i].price);
return 0;
}
  1. typedef可以与结构体定义结合起来
1
2
3
4
typedef struct book{
char name[100];
int price;
}Book;

他和上述typedef struct book book是等价的哦

  1. typedef不仅仅只能起一个名字 他能起好多名字
1
2
3
4
typedef struct book{
char name[100];
int price;
}Book,A,B;

这样Book books[10],A books[10],B books[10]都是一个意思

  1. typedef 可以定义指针哦
1
2
3
4
typedef struct book{
char name[100];
int price;
}*BookPointer;

Book *bookBookPointer book是等价的哦 book都是一个struct book的指针哦

就是在定义Book的指针的时候少写一个*

以上的究极缝合 就会出现课本上的链表的定义

1
2
3
4
typedef struct LNode{
ElemType data;
struct LNode *next;//c语言特点 必须要加struct 他不会管typedef重命名的
}LNode,*LinkNode;

LNode表示一个正常的结点

*LinkNode就表示一个指针哦 一般用来指向头结点

结构体创建

结构体赋值

  1. 创建时赋值
1
2
3
4
5
int main() {
Book book={"结构体真棒",250};
printf("%s %d\n", book.name, book.price);
return 0;
}
  1. 先定义后赋值
1
2
3
4
5
6
7
int main() {
Book book;
strcpy(book.name, "结构体真棒");
book.price=250;
printf("%s %d\n", book.name, book.price);
return 0;
}

3.乱序赋值

1
2
3
4
5
int main() {
Book book={.price=250,.name="结构体真棒"};
printf("%s %d\n", book.name, book.price);
return 0;
}

结构体指针

  1. 先申请空间在赋值
1
2
3
4
5
6
7
int main() {
Book *book =(struct book*) malloc(sizeof(Book));
strcpy(book->name,"结构体真棒");
book->price=250;
printf("%s %d\n",book->name,book->price);
return 0;
}
  1. 创建时引用
1
2
3
4
5
6
int main() {
Book A ={"结构体真棒",250};
Book *book=&A;
printf("%s %d\n",book->name,book->price);
return 0;
}
  1. c++特有 new Book()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<cstring>
using namespace std;
typedef struct book{
string name;
int price;
}Book;
int main(){
Book *book=new Book();//new 出来返回的是个地址和malloc 差不多
book->name="结构体真棒";
book->price=250;
cout<<book->name<<" "<<book->price<<endl;
return 0;
}

结构体引用内部值的方式

  1. 非指针直接用 ..
1
2
3
4
5
int main() {
Book book={.price=250,.name="结构体真棒"};
printf("%s %d\n", book.name, book.price);
return 0;
}
  1. 指针用->
1
2
3
4
5
6
7
int main() {
Book *book =(struct book*) malloc(sizeof(Book));
strcpy(book->name,"结构体真棒");
book->price=250;
printf("%s %d\n",book->name,book->price);
return 0;
}

结构体传值

  1. 作为形参
1
2
3
4
5
6
7
8
9
10
11
void f(Book book){
book.price=500;
strcpy(book.name,"结构体真好");
printf("%s %d\n",book.name,book.price);
}
int main() {
Book book ={"结构体真棒",250};
f(book);
printf("%s %d\n",book.name,book.price);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
void f(Book book){
book.price=500;
strcpy(book.name,"结构体真好");
printf("%s %d\n",book.name,book.price);
}
int main() {
Book A ={"结构体真棒",250};
Book *book=&A;
f(*book);
printf("%s %d\n",book->name,book->price);
return 0;
}

结果
结构体真好 500
结构体真棒 250

  1. 作为实参
1
2
3
4
5
6
7
8
9
10
11
void f(Book *book){
book->price=500;
strcpy(book->name,"结构体真好");
printf("%s %d\n",book->name,book->price);
}
int main() {
Book book ={"结构体真棒",250};
f(&book);
printf("%s %d\n",book.name,book.price);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
void f(Book *book){
book->price=500;
strcpy(book->name,"结构体真好");
printf("%s %d\n",book->name,book->price);
}
int main() {
Book book ={"结构体真棒",250};
f(&book);
printf("%s %d\n",book.name,book.price);
return 0;
}

c++特有的引用

1
2
3
4
5
6
7
8
9
10
11
void f(Book &book){
book.name="结构体真好";
book.price=500;
cout<<book.name<<" "<<book.price<<endl;
}
int main() {
Book book ={"结构体真棒",250};
f(book);
cout<<book.name<<" "<<book.price<<endl;
return 0;
}

结果
结构体真好 500
结构体真好 500

结构体练习–链表的实现与方法

结点表示

c语言不会先去看ttypedef重命名的 所以要加struct

1
2
3
4
typedef struct node {
int val;
struct node *next;/
}node;

c++ typedef有无结点内都不用加struct

1
2
3
4
struct node {
int val;
node *next;
};

静态链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
struct node {
int val;
struct node *next;
};
int main() {
struct node node1 = {1, NULL};
struct node node2 = {2, NULL};
struct node node3 = {3, NULL};
node1.next = &node2;
node2.next = &node3;
struct node *p=&node1;
while(p){
printf("%d ",p->val);
p=p->next;
}
return 0;
}

动态链表 以及常用方法

为了以后方便直接用 就没有把headNode直接提出来成全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
int data;
struct Node *next;
} Node;

Node *createList() {
Node *headNode = (Node *) malloc(sizeof(Node));
//headNode 成为了结构体变量
//变量使用前必须被初始化
headNode->next = NULL;
return headNode;
}

Node *createNode(int data) {
Node *node = (Node *) malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}

void printList(Node *headNode) {
Node *p = headNode->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}

void insertHead(Node *headNode, int data) {
Node *node = createNode(data);
node->next = headNode->next;
headNode->next = node;
}

void insertArrayByHead(Node *headNode, int data[], int len) {
for (int i = 0; i < len; i++)
insertHead(headNode, data[i]);
}

void insertTail(Node *headNode, int data) {
Node *node = createNode(data);
Node *p = headNode;
while (p->next)p = p->next;
p->next = node;
}

void insertArrayByTail(Node *headNode, int data[], int len) {
Node *tail = headNode;
while (tail->next)tail = tail->next;
for (int i = 0; i < len; i++) {
Node *node = createNode(data[i]);
tail->next = node;
tail = tail->next;
}
}

int deleteNodeByIndex(Node *headNode, int k) {//删除第k号索引的结点
if (!headNode || k < 0)return 0;
Node *p = headNode;
for (int i = 0; i < k && p->next; i++)
p = p->next;
if (!p)return 0;//链表都没有k号索引结点
Node *t = p->next;
p->next = t->next;
free(t);
return 1;
}

int deleteNodeByData(Node *headNode, int data) {//删除链表中与data值相同的结点
if (!headNode)return 0;
Node *p = headNode;
while (p->next) {
if (p->next->data == data) {
Node *t = p->next;
p->next = t->next;
free(t);
} else
p = p->next;
}
return 1;
}

int getListLength(Node *headNode) {//获取链表长度
int len = 0;
Node *p = headNode->next;
while (p) {
p = p->next;
len++;
}
return len;
}

void reverseList(Node *headNode) {//反转链表
//每次取一个结点插到对头就行了
Node *p = headNode->next;
headNode->next=NULL;
while (p) {
Node *n = p->next;//
p->next = headNode->next;
headNode->next = p;
p = n;
}
}

int main() {
Node *headNode = createList();
int data[6] = {1, 2, 3, 4, 5,6};
insertArrayByTail(headNode, data, sizeof(data) / sizeof(data[0]));
reverseList(headNode);
printList(headNode);
return 0;
}