数组的分类:便于遍历
静态数组:int arr[10]数据过多造成空间溢出,数据过小空间浪费
动态数组:malloc calloc realloc 合理利用空间不能快捷的插入或删除数据(会涉及到大量的数据移动)
知识点一:链表的基本概念
链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构
链表由一系列节点( 链表中每一个元素称为节点)组成,节点在运行时动态生成(malloc) ,每个节点包括两个部分:
1)存储数据元素的数据域 2)存储下一个节点地址的指针域
知识点二:链表结点的定义(结构体实现)
typedef struct stu
{//数据域(自定义)int num;char name[32];float score;//指针域struct stu *next; //保存 下一个节点的地址:
}STU;
知识点三:静态链表
typedef struct stu
{int num;char name[32];float score;struct stu *next; //保存 下一个节点的地址:
}STU;
void test1()
{ STU datal = {100, "德玛",59};STU data2 = {101, "小炮",89};STU data3 = {102, "小法",79};STU data4 = {103,"盲僧",99};STU data5 = {104, "快乐风男",39};//链表头STU *head = NULL;head = &datal;datal.next = &data2;data2.next = &data3;data3.next = &data4;data4.next = &data5;data5.next = NULL;//遍历链表STU *pb = head;while(pb != NULL){printf("%d %s %f\n", pb->num, pb->name, pb->score) ;pb = pb->next; //pb指向下一一个节点}
}
知识点四:动态链表
1、布局整个框架(main.c)
#include<stdio.h>
#include<string.h>
void stu_help(void);
int main(int argc,char *argv[])
{stu_help();while(1){printf("请输入操作指令:");char cmd[32] = "";scanf( "%s",cmd);if(strcmp(cmd,"help") == 0){printf("-----help------\n");}else if(strcmp(cmd,"insert") == 0){printf("-----insert------\n");}else if(strcmp(cmd,"print") == 0){printf("-----print------\n");}else if(strcmp(cmd,"search") == 0){printf("-----search------\n");}else if(strcmp(cmd,"delete") == 0){printf("-----delete------\n");}else if(strcmp(cmd,"free") == 0){printf("-----free------\n");}else if(strcmp(cmd,"quit") == 0){break;}} return 0;
}
void stu_help(void)
{printf("############################\n");printf("#help:打印帮助信息 #\n");printf("#insert:插入链表节点 #\n");printf("#print:遍历链表节点信息 #\n");printf("#search:查询链表节点 #\n");printf("#delete:删除链表节点 #\n");printf("#free:释放链表 #\n");printf("#quit:退出 #\n");printf("############################\n");return;
}
2、链表插入节点之头部之前插入
3、在链表尾部插入
4、链表的有序插入
知识点五:链表查询某个节点
知识点六:删除链表指定节点
知识点七:链表的释放
STU* free_link(STU *head)
{//1、判断链表是否存在if(head == NULL)//不存在 {printf("link not found\n");retrun head;} else //存在 {STU *pb = head;//逐个节点释放while(pb != NULL){//head保存下一个节点的位置head = pb->next;//释放pb指向的节点free(pb);//pb指向headpb = head; }printf("链表已经释放完毕\n"); return head;}return head;
}
知识点八:链表逆序
STU* reverse_link(STU *head)
{//1、判断链表是否存在if(head == NULL)//不存在 {printf("link not found\n");retrun head;} else//存在 {//int *p,num; //p为int *, num为intSTU *pb,*pr; //pb为STU *,pr 为STU *//pb保存head->next ( 原因head->next会置NULL)pb = head->next;//将head->next置NULL(原因:头节点变尾节点)head->next = NULL;while(pb != NULL){//pr 保存pb->next ( 原因:pb->next会指向head)pr = pb -> next;//pb->next指向head ( 原因:逆转方向)pb->next = head ;//保存逆转方向的代码可以重复执行head = pb;pb = pr;}return head;}return head;
}
知识点九:链表排序
选择法排序:(以数组实现)
#include<stdio.h>
int main()
{int arr[10] = {0};int n = sizeof(arr)/sizeof(arr[0]);int i = 0,j = 0,min = 0;printf("请输入%d个int数据\n", n);for(i = 0; i<n; i++){scanf("%d",arr+i);}for(i = 0;i < n-1;i++){for(min = i,j = min+1;j < n;j++){if (arr[min] > arr[j])min = j;}if (min != i){int tmp = 0;tmp = arr[i];arr[i] = arr[min];arr [min] = tmp;}}for(i = 0;i < n;i++) {printf("%d ",arr[i]);}printf("\n");return 0;
}
选择法排序:(以链表实现)
知识点十:认识双向链表
知识点十一:双链表插入
知识点十二:双向链表删除指定节点
知识点十三:结构的浅拷贝和深拷贝
1、指针变量作为结构体的成员
typedef struct
{int num;char *name;//指针变量作为结构体的成员
}DATA;
void test01()
{DATA data = {100, "hehehehaha"};printf("%d\n",sizeof(DATA));//8字节printf("num = %d\n" ,data.num) ;//指针变量作为结构体的成员保存的是空间的地址printf("name = %s\n", data. name);
}
2、指针变量作为结构体的成员 操作前 必须有合法空间
void test02()
{DATA data;printf( "%d\n",sizeof(DATA));printf("num = %d\n", data.num) ;//指针变量作为结构体的成员操作前必须有合法的空间//data.name = "hehe" ;//给name事先申请一块堆区空间data.name = (char *)calloc(1,10);strcpy(data.name,"hahaha");printf("name = %s\n", data.name ) ;//如果name指向堆区空间一定要记得释放if(data. name != NULL ){free(data. name) ;data. name = NULL;}
}
3、指针变量作为结构体成员,结构体变量间的赋值操作容易导致“浅拷贝”发生
运行结果:出现段错误
两个结构体变量中的指针成员指向同-块堆区空间
void test03()
{DATA data1;DATA data2;data1.num = 100;data1.name = (char *)calloc(1,10);strcpy(data1.name,"my data");//指针变量作为结构体的成员结构体变量间的赋值操作容易导致"浅拷贝”发生data2 = data1; //"浅拷贝”printf("data2: num = %d,name = %s\n", data2.num,data2.name); if(datal.name != NULL){free(data1.name);data1.name = NULL;}if( data2.name != NULL){free(data2.name);data2.name = NULL;}
}
4、深拷贝
前提:是指针变量作为结构体的成员
两个结构体变量中的指针成员指向各自的堆区空间
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{int num;char *name;
} DATA;
void test01()
{DATA datal ;DATA data2 ;datal.num = 100;datal.name = (char *)calloc(1,12);strcpy (datal.name,"my data");data2. num = datal. num;//为结构体变量 申请 独立空间 data2.name = (char *)calloc(1,12);strcpy(data2.name,datal.name) ;printf("data1:num = %d,name = %s\n",datal.num,datal.name);printf("data2:num = %d,name = %s\n",data2.num,data2.name);if (datal.name!=NULL){free(datal.name);datal.name = NULL;}if (data2.name!=NULL){free(data2.name);data2.name = NULL;}
}