一、跨函数分配内存:只可以通过动态来实现。
eg:#include<stdlib.h>
main()
{
int *p;
fun(&p);
...
}
int fun(int **q)
{
*q = (int *)malloc(4);
}
二、数据存储-->线性结构
线性结构:把所有的结点用一根直线穿起来
连续存储(eg:数组)
void init_arr();
bool append_arr();//追加
bool insert_arr();//插入
bool delete_arr();
int get();
bool is_empty();
bol is_full();
void sort_arr();
void show_arr();//输出
void inversion_arr();//遍历
typedef int ZHANGSAN //为int重新取一个名字
int为数据类型
同理,下面这个也是数据类型
struct Student
{
int sid;
char name[100];
char sex;
}
因此
typedef struct Student
{
int sid;
char name[100];
char sex;
} ST; //把那整个数据类型(struct Student)重新定义为一个ST。
typedef struct Student
{
int sid;
char name[100];
char sex;
} * PST; //把那整个数据类型(struct Student *)重新定义为一个PST(PST是一个指针)。
typedef struct Student
{
int sid;
char name[100];
char sex;
} * PSTU, STU; //等价于STU代表了struct Student,PSTU代表了struct Student *。
离散存储(链表)
定义:链表:a:n个节点离散分配;b:彼此通过指针相连;c:每个节点只有一个前驱节点(首节点没有),每个节点只有一个后续节点(尾节点没有)。
专业术语:
首节点:第一个有效的节点
尾节点:最后一个有效的节点,它的指针域是空的,因为是最后一个。
头节点:第一个有效节点之前的那个节点,它并不存放有效数据,它的存在是为了方便对链表的 操作,头节点的数据类型和首节点一样。
头指针:指向头节点的指针变量,它存放了头节点的地址
尾指针:指向尾节点的指针变量
若希望通过一个函数来对链表进行处理,我们至少需要接收链表的哪些信息
长度、首节点、尾节点均不是必须的,头指针是必须的。
typedef struct Node
{
int data; //数据域
struct Node * pNext;//指针域
}NODE,*PNODE; //NODE等价于struct Node,PNODE等价于struct Node *
分类:
单链表:
双链表:每一个节点有两个指针域,
循环链表:尾节点指向头节点;可以通过任何一个节点找到其它所有的节点
非循环链表:
算法:
遍历:
查找:
清空:
销毁:
求长度:
排序:
插入节点(q为指向该节点的指针):q->pNext = p->pNext;p->pNext = q;
删除节点: r = p->pNext; p->pNext = p->pNext->pNext;free(r);
free p;删除p指向节点所占内存,不是删除p本身所占内存。
链表的优缺点:
线性结构的两种常见应用之一 : 栈(函数调用与内存分配都要用到)
线性结构的两种常见应用之二 : 队列(所有和时间有关的操作都要用到)
程序:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data; //数据域
struct Node * pNext;//指针域
}NODE,*PNODE; //NODE等价于struct Node,PNODE等价于struct Node *
//函数声明
PNODE create_list(void);
void traverse_list(PNODE pHead);
int main(void)
{
PNODE pHead = NULL; //等价于struct Node * pHead = NULL;
pHead = create_list(); //create_list()功能:创建一个非循环单链表,并将该链表的首地址赋给 pHead
//一个函数分配好内存让另一个函数去使用,前提是动态分配
traverse_list(pHead);
return 0;
}
//void f()
//{
// int i;
// int * p = (int *)malloc(100);//当f运行完之后,p本身的内存释放了,满是malloc动态分 配的那100个字节还在。
//}
PNODE create_list(void)
{
int i;
int len;//用来存放有效节点的个数
int val;//用来临时存放用户输入的节点的值
//分配了一个不存放有效数据的头节点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if(NULL==pHead)
{
printf(“fail to allocate,procedure expired\n”);
exit(-1);
}
PNODE pTail = pHead;
pTail->pNext = NULL;
printf(“please input the amout of point: len = ”);
scanf(“%d”,&len)
for(i=0;i<len; ++i)
{
printf(“please input the th %d point ”,i+1);
scanf("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL==pNew)
{
printf(“fail to allocate,procedure expired\n”);
exit(-1);
}
pNew->data = val;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(PNODE pHead)
{
while(NULL!=p)
{
printf("%d",p->data);
p = p->pNext;
}
printf("\n");
}