#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/*
struct Teacher
{
char name[64];
int id;
char *p;
char **p2;
};
typedef struct Teacher Teacher ;
*/
typedef struct Student
{
char name[64];
int id;
}Student;
typedef struct Teacher
{
char name[64];
int id;
char *p;
char **p2;
Student s1;
Student *p3;
}Teacher;
//1 结构体中套一个结构体
//2 结构体的指针
//3 结构中套一个 自己类型的结构体元素。。。err
//4 结构体中 套一个 指向自己类型的指针
//数据类型本质:固定大小内存块的别名
/*
typedef struct AdvTeacher
{
char name[64];
int id;
struct AdvTeacher AdvTeacher;
}AdvTeacher; //在自己类型大小 还没有确定的情况下 引用自己类型的元素 是不正确的
//结构体不能嵌套定义 (确定不了数据类型的内存大小,分配不了内存)
*/
typedef struct AdvTeacher2
{
char name[64];
int id;
struct AdvTeacher2 *p2;
}AdvTeacher;
//函数的嵌套调用 和 结构数据类型嵌套定义 是两个不同的概念
void main11()
{
Teacher t1;
//AdvTeacher advT1; //
printf("hello...\n");
system("pause");
main();
return ;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//类
typedef struct Teacher
{
int data;
struct Teacher *next;
}Teacher;
//静态链表
//固定个数 结点的内存生命周期
//动态链表
Teacher *CreatlIST(Teacher **retHead, Teacher **retEnd, Teacher **retmid)
{
static Teacher t1, t2, t3,t4;
Teacher *p = NULL;
t1.data = 1;
t2.data = 2;
t3.data = 3;
t4.data = 4;
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = 0;
p = &t1;
while (p)
{
printf("data:%d \n", p->data);
p = p->next; //指针的下移
}
*retHead = &t1;
*retEnd = &t4;
*retmid = &t2;
return &t4;
}
void main()
{
Teacher *head;
Teacher *end;
Teacher *end2;
Teacher *mid;
end2 = CreatlIST(&head,&end,&mid);
printf("head:%d\n",head->data);
printf("end:%d\n", end->data);
printf("end:%d\n", end2->data);
printf("mid:%d\n", mid->data);
printf("hello...\n");
system("pause");
return;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct Node
{
int data;
struct Node *next;
}SLIST;
SLIST *SList_Create(); //创建链表
int SList_Print(SLIST *pHead); //遍历链表
int SList_NodeInsert(SLIST *pHead, int x, int y); //插入值 在x值之前 删除y
int SList_NodeDel(SLIST *pHead, int y);
int SList_Destory(SLIST *pHead);
SLIST *SList_Create()
{
SLIST *pHead, *pM, *pCur;
int data;
//创建头节点 并初始化
pHead = (SLIST *)malloc(sizeof(SLIST));
if (pHead == NULL)
{
return NULL;
}
pHead->data = 0;
pHead->next = NULL;
printf("\nplease enter you data: ");
scanf("%d", &data);
pCur = pHead;
while (data != -1)
{
//创建业务节点 并初始化 不断接受输入 malloc新结点
pM = (SLIST *)malloc(sizeof(SLIST));
if (pM == NULL)
{
return NULL;
}
pM->data = data;
pM->next = NULL;
//2 新结点 入链表
pCur->next = pM;
//3 新结点变成当前节点
pCur = pM; //链表结点的尾部追加
printf("\nplease enter you data: ");
scanf("%d", &data);
}
return pHead;
}
int SList_Print(SLIST *pHead)
{
SLIST *tmp = NULL;
if (pHead == NULL)
{
return -1;
}
tmp = pHead->next;
printf("\nBegin\t");
while (tmp)
{
printf("%d ", tmp->data);
tmp = tmp->next;
}
printf("\tEnd");
return 0;
}
int SList_NodeInsert(SLIST *pHead, int x, int y)
{
SLIST *pM, *pCur, *pPre;
//创建新的业务节点pM
pM = (SLIST *)malloc(sizeof(SLIST));
if (pM == NULL)
{
return -1;
}
pM->next = NULL;
pM->data = y;
//遍历链表
pPre = pHead;
pCur = pHead->next;
while (pCur)
{
if (pCur->data == x)
{
break;
}
pPre = pCur;
pCur = pCur->next;
}
//让新结点 连接 后续链表
pM->next = pPre->next;
//让前驱节点 连接 新结点
pPre->next = pM;
return 0;
}
int SList_NodeDel(SLIST *pHead, int y)
{
SLIST *pCur, *pPre;
//初始化状态
pPre = pHead;
pCur = pHead->next;
while(pCur != NULL)
{
if (pCur->data == y)
{
break;
}
pPre = pCur;
pCur = pCur->next;
}
//删除操作
if (pCur == NULL)
{
printf("没有找到结点值为:%d 的结点\n", y);
return -1;
}
pPre->next = pCur->next;
if (pCur != NULL)
{
free(pCur);
}
return 0;
}
int SList_Destory(SLIST *pHead)
{
SLIST *tmp = NULL;
if (pHead == NULL)
{
return -1;
}
while (pHead != NULL)
{
tmp = pHead->next;
free(pHead);
pHead = tmp;
}
return 0;
}
int SList_Reverse(SLIST *pHead)
{
SLIST *p = NULL; //前驱指针
SLIST *q = NULL; //当前指针
SLIST *t = NULL; //缓存的一个结点
if (pHead==NULL || pHead->next == NULL ||pHead->next->next ==NULL )
{
return 0;
}
//初始化 //前驱结点
p = pHead->next;
q = pHead->next->next;
//p = pHead; //代码能兼容
//q = pHead->next;
//一个结点 一个结点的逆置
while(q)
{
t = q->next; //缓冲后面的链表
q->next = p; //逆置
p = q; //让p下移一个结点
q = t;
}
//头节点 变成 尾部结点 后 置null
pHead->next->next = NULL;
pHead->next = p; //
return 0;
}
void main()
{
int ret = 0;
SLIST *pHead = NULL;
pHead = SList_Create();
ret = SList_Print(pHead);
ret = SList_NodeInsert(pHead, 20, 19);
ret = SList_Print(pHead);
ret = SList_NodeDel(pHead, 19);
ret = SList_Print(pHead);
ret = SList_Reverse(pHead);
ret = SList_Print(pHead);
SList_Destory(pHead);
printf("hello...\n");
system("pause");
return ;
}
链表是单向的,当前节点的位置保存在前驱节点的指针域,所以在插入的时候,要先将新节点的指针域指向当前节点(新节点插入在该节点之前),然后当前节点的前驱结点的指针域指向新节点。需要的辅助变量有三个:
pPre、pCur(指向要比较的节点)、pM(新增节点)
//顺序遍历单向动态链表
int SList_Print(SLIST *pHead)
{
SLIST *tmp = NULL;
if (pHead == NULL)
{
return -1;
}
tmp = pHead->next;//tmp指向第一个节点(不是头结点)
printf("\nBegin\n");
while (tmp)
{
printf("%d\n",tmp->data);
tmp = tmp->next;//tmp永远指向要打印的当前节点
}
printf("\nEnd\n");
return 0;
}
/*链表逆置*/
int SList_Reverse(SLIST * pHead)
{
SLIST * pPre = NULL;//前驱节点
SLIST * pCur = NULL;//当前节点
SLIST * pNext = NULL;//后继节点
/*合法性检测或者只有头节点或者只有一个节点和头结点*/
if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL)
{
return -1;
}
/*初始化的时候将前驱结点指向第一个节点*/
pPre = pHead->next;
pCur = pHead->next->next;//当前节点指向第二个节点
while (pCur)
{
pNext = pCur->next;//保存第三个节点的位置或者是NULL(链表尾)
pCur->next = pPre;//当前节点的指针域指向前驱结点
/*当前节点和前驱结点一起往后移动一个节点*/
pPre = pCur;
pCur = pNext;
}
pHead->next->next = NULL;//修正第一个节点的指针域指向NULL变成新的链表尾
pHead->next = pPre;//修正头结点指向新链表的第一个节点(旧链表的最后一个节点)
return 0;
}
typedef struct __node{
int data;//数据域
struct __node *next;//(指向自己结构体类型的)指针域
}SLIST;
/*创建链表(尾插法插入新节点)*/
SLIST *SList_Create()
{
SLIST * pHead = NULL;//辅助指针变量之一,表示头结点
SLIST * pCur = NULL;//让新节点变成当前节点的辅助指针变量
SLIST * pM = NULL;//用于指向信malloc出的节点的辅助指针变量
int data = 0;
/*0.创建头结点*/
pHead = (SLIST*)malloc(sizeof(SLIST));
if (pHead == NULL)
{
return NULL;
}
pHead->data = 0;
pHead->next = NULL;
pCur = pHead;//pCur永远指向最后一个节点
printf("\nplease input your data:");
scanf("%d",&data);
/*1.循环malloc出新节点*/
while (data != 0)
{
pM = (SLIST*)malloc(sizeof(SLIST));
if (pM == NULL)
{
return NULL;
}
pM->data = data;
pM->next = NULL;
/*2.新节点入链表*/
pCur->next = pM;
/*3.新节点变成当前节点*/
pCur = pM;//pCur永远指向最后一个节点
printf("\nplease input your data:");
scanf("%d", &data);
}
return pHead;
}
/*在x之前插入y*/
int SList_NodeInsert(SLIST * pHead,int x,int y)
{
SLIST * pPre = NULL;//辅助指针变量之一,表示要插入新节点的前驱结点
SLIST * pCur = NULL;//表示要插入新节点的后继结点
SLIST * pM = NULL;//用于指向新节点
if (pHead == NULL)//合法性判断
{
return -1;
}
pPre = pHead;//初始化的时候让前驱结点指向头结点
pCur = pHead->next;//初始化的时候让后继结点指向第一个节点(不是头结点)
pM = (SLIST*)malloc(sizeof(SLIST));//为新节点开辟空间
if (pM == NULL)
{
return -1;
}
/*初始化新节点*/
pM->data = y;
pM->next = NULL;
while (pCur)//pCur指向要插入节点的后继节点,当pCur==NULL的时候表示遍历到链表尾
{
if (pCur->data == x){//没有到链表尾的时候判断该节点是否是要寻找的比较节点(这里是后继节点)
break;
}
/*不满足条件时往后挪动辅助指针变量的位置*/
pPre = pCur;
pCur = pCur->next;
}
/*不管原链表存不存在X节点,都会将新节点插入链表,不存在的时候插入到链表尾,存在的时候插入到X节点前面*/
pM->next = pCur;
pPre->next = pM;
return 0;
}
/*删除链表中数据域为y的节点*/
int SList_NodeDelete(SLIST * pHead, int y)
{
SLIST *pPre = NULL;//指向要删除节点的前驱结点
SLIST *pCur = NULL;//指向要删除的节点或者直到链表尾
if (pHead == NULL)//合法性检测
{
return -1;
}
/*初始化的时候前驱结点指向头结点,要删除节点指向第一个非头结点的节点即使是空指针(即链表除了头结点没有任何元素)*/
pPre = pHead;
pCur = pHead->next;
while (pCur)//只要当前节点不是空指针(即没有到链表尾)
{
if (pCur->data == y)//满足条件不在移动辅助指针变量的指向
{
break;
}
/*不满足条件时往后挪动辅助指针变量的位置*/
pPre = pCur;
pCur = pCur->next;
}
if (pCur == NULL)//寻找到链表尾没有发现要删除的节点
{
printf("cant find the node of y\n");
return -2;
}
pPre->next = pCur->next;//删除节点
if (pCur != NULL)
{
free(pCur);//内存回收
pCur = NULL;//避免野指针
}
return 0;
}
/*销毁链表*/
int SList_Destroy(SLIST ** pHead)
{
SLIST *pCur = NULL;//指向要销毁的当前节点
SLIST *pTmp = NULL;//用于缓存要销毁的节点的数据,否则一旦销毁以后找不到后继节点,实际上就是指向后一个节点
if (NULL == pHead)
{
return -1;
}
if (NULL == *pHead)
{
return -1;
}
pCur = (SLIST *)(*pHead);//初始化的时候将pCur指向头结点
while (pCur)
{
pTmp = pCur->next;//缓存上一个节点的数据以便找到后继节点
free(pCur);
pCur = pTmp;//将pCur指向后继节点
}
*pHead = NULL;//避免野指针
return 0;
}