一、数据结构
1.在linux下,存储数据的方式
①永久性存储:文件、数据库
②程序中存储:变量、数组、链表、栈、队列、二叉树 -->统一称为数据结构
栈、队列、二叉树都是链表的拓展。
2.数据结构:用于存储数据的一个模型。
变量:存储单个相同类型的数据。
数组:存储多个相同同类型数据,数组的内存在空间上时连续的。
链表:存储多个个相同类型数据,链表在内存上的空间是不连续的。
3.数组与链表储存规则的区别
数组:
① 存储区域:栈区/数据段(静态区/全局区)
②数组特点:在内存上申请的空间必定时连续的。
1)只需要通过下标就能够访问数组中任意一个成员
2)在定义数组的时候必须先声明数组的大小。限制数组空间操作的大小。
3)再给数组赋值的时候,必须先检查好空间的大小,不然容易导致越界访问非法内存。
链表:
①存储区域:堆区
②链表特点:
1)在内存上申请的空间不一定是连续的。
2)链表成员除了储存自身的数据之外,还需要存储下一个成员的地址,每一个 成员都可以通过地址找到下一个成员。
3)链表不需要提前声明空间的大小,只要运行内存足够大,那么链表就会无限的延伸下去。
4.链表的模型组成:
①节点:链表是由若干个个体来组成的,而这些个体我们称之为节点。
②头节点:排在链表最开头的节点称之为头节点
头节点的特征:数据域是无效的(有数据域但是不存放数据)
③数据域:储存自身的数据
数据域中可以存放什么:(内置数据类型/数组/指针/结构体)
④指针域:存储下一个成员的地址(因为每一个节点都是一个结构体,所以这个指针域都是结构体指针)。
2.如何在程序中表示一个节点
struct list node{
/*数据域*/
/*指针域*/
}:
举例:设计一个链表存放int型的数据
//写一个链表每个节点都存放int数据
struct list_node{
int data;
struct list_node *next;
};
//一个学生的链表
struct list_node{
char name[10];
int age;
struct list_name *next;
};
//实现一个链表存储10 20 30
#include <stdio.h>
#include <stdlib.h>
struct list_node
{
int data;
struct list_node *next;
};
struct list_node *init_list_head();
void insert_node_to_tail(struct list_node *head, int num);
void show_list_node(struct list_node *head);
void intsert_head_node(struct list_node *head, int num);
int search_list_node(struct list_node *head, int num);
void show_node_data(struct list_node *p);
void delete_list(struct list_node*head);
void delete_list_node(struct list_node *head, int num);
int main(int argc, char *argv[])
{
//初始化链表的头节点
int num;
struct list_node *head = NULL;
head = init_list_head();
insert_node_to_tail(head, 10);
insert_node_to_tail(head, 20);
insert_node_to_tail(head, 30);
//插入数据到头节点
intsert_head_node(head, 55);
//根据特征值搜索节点
search_list_node(head, 8);
//删除某个节点
delete_list_node(head, 20);
//遍历整个链表
show_list_node(head);
//删除整个链表;
delete_list(head);
return 0;
}
//申请头指针
struct list_node *init_list_head()
{
//为头指针申请空间
struct list_node *head = malloc(sizeof(struct list_node));
if (head == NULL)
{
perror("malloc");
}
//为头节点的数据域和指针域赋值
head->next = NULL;
return head;
}
//尾插法
void insert_node_to_tail(struct list_node *head, int num)
{
struct list_node *new = malloc(sizeof(struct list_node));
if (new == NULL)
{
perror("malloc");
}
//为新节点的数据域和指针域赋值
new->data = num;
new->next = NULL;
//寻找最后一个节点。
struct list_node *p = NULL;
for (p = head; p->next != NULL; p = p->next)
;
//循环出来时p->next一定为空,p一定指向最后一个节点
//只需要将最后一个节点指针域指向新节点
p->next = new;
}
void show_list_node(struct list_node *head)
{
struct list_node *p = NULL;
for (p = head; p->next != NULL; p = p->next)
{
printf("数据:%d\n", p->next->data);
}
}
//头插法
void intsert_head_node(struct list_node *head, int num)
{
struct list_node *p = malloc(sizeof(struct list_node));
if (p == NULL)
{
perror("malloc");
}
p->data = num;
p->next = head->next;
head->next = p;
}
//查询
int search_list_node(struct list_node *head, int num)
{
struct list_node *p = NULL;
for (p = head->next; p != NULL; p = p->next)
{
if (p->data == num)
{
show_node_data(p);
return 0;
}
}
printf("not find node\n");
return -1;
}
//打印
void show_node_data(struct list_node *p)
{
printf("p->data:%d\n", p->data);
}
//删除
void delete_list_node(struct list_node *head, int num)
{
struct list_node *p = NULL;
struct list_node *q = NULL;
//遍历链表寻找特征值
for (q = head, p = head->next; p != NULL; q = p, p = p->next)
{
if (p->data == num)
{
q->next = p->next;
free(p);
}
}
}
//删除整个链表
void delete_list(struct list_node*head){
struct list_node *p=NULL;
struct list_node *q=NULL;
for(q=head,p=head;p!=NULL;q=p){
p=p->next;
free(q);
}
}