1.认清结构体是如何定义的
#include<stdio.h>
#define DataType int
//1.
struct Node {
DataType data;
struct Node*next;
};
//2.
struct Node1 {
DataType data;
struct Node1*next;
}Node1,Node2[10];
//3.
typedef struct Node3 {
DataType data;
struct Node*next;
}ListNode;
//4
typedef struct Node4 {
DataType data;
struct Node*next;
}*LinkList, ListNode1;
int main()
{
//1
//标准的链表空间开辟:
struct Node *p = (struct Node *)malloc(sizeof(struct Node));
//结构体释放
struct Node m = { 56,p };//直接定义m
free(p);
//2
//是在上方就定义好了类似上方结构体m的东西
//Node2[10]是一排结构体
//3
//就是可以用ListNode代替struct Node3
//4
//用* LinkList代替struct Node4,需要借助类似3
//里面的思想要好好考虑
LinkList n = (LinkList)malloc(sizeof(ListNode1));
return 0;
}
2.线性表的链式存储
//线性表的链式表示
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define DataType int
//单链表的定义
typedef struct Node {
DataType data;
struct Node*next;
}ListNode, *LinkList;
//头插法建立单链表,头结点head不是第一个节点,他的data里无数据
LinkList Creat_list1(LinkList head) {
head = (LinkList)malloc(sizeof(ListNode));
ListNode *node = NULL;
int count = 0;
head->next = NULL;
node = head->next;
printf("Input the node number: ");
scanf("%d", &count);
for (int i = 0; i < count; i++)
{
node = (LinkList)malloc(sizeof(ListNode));
node->data = i;
node->next = head->next;
head->next = node;
}
return head;
}
//尾插法建立单链表
LinkList Creat_list2(LinkList head) {
head = (LinkList)malloc(sizeof(ListNode));
LinkList node = NULL;
LinkList end = NULL;
head->next = NULL;
end = head; //head是不可能变化的,需要选取一个节点,不断让他等于链表的结尾
int count = 0;
printf("Input node number: ");
scanf("%d", &count);
for (int i = 0; i < count; i++) {
node = (LinkList)malloc(sizeof(ListNode));
node->data = i;
end->next = node;
end = node; //不停让他等于结尾
}
end->next = NULL;
return head;
}
//判断是否为空
int ListEmpty(LinkList head)
{
if (head->next == NULL)
return 1;
else
return 0;
}
//按序号查找
ListNode *Get(LinkList L, int i)//在这里ListNode *和LinkList相同
{
int j = 1;
ListNode *p = L->next;
if (i == 0)
return L;
if (i < 1)
return NULL;
while (p&&j < i)
{
p = p->next;
j++;
}
//因为是返回链表的一个节点,所以需要获取他的地址,所以函数类型 是ListNode *类型
return p;
}
//按内容(值)查找
LinkList *LocateElem(LinkList L, DataType e)
{
ListNode *p = L->next;
while (p != NULL&&p->data != e)
p = p->next;
//因为是返回链表的一个节点,所以需要获取他的地址,所以函数类型 是ListNode *类型
return p;
}
//遍历链表
void TraverseList(LinkList head)
{
LinkList p = head->next;
if (head->next == NULL)
{
printf("链表为空!");
}
else
{
while (p != NULL)
{
printf("%d", p->data);
p = p->next;
}
}
}
//插入结点
//需要调用按序号查找函数Get
//后插
LinkList Insert_back(LinkList head, DataType e, int i)
{
LinkList m;
//= (LinkList)malloc(sizeof(ListNode));
//这里m的空间在Get函数里由p分配,然后把地址给m,所以m没有用到上面那行
m=Get(head, i-1);
LinkList s = (LinkList)malloc(sizeof(ListNode));
s->data = e;
s->next = m->next;
m->next = s;
return head;
}
//前插操作,这里的思想还是查找上方的那个结点,此改变此结点内数据实现
LinkList Insert_front(LinkList head, DataType e, int i)
{
LinkList p;
p = Get(head,i-1);
LinkList s = (LinkList)malloc(sizeof(ListNode));
s->data = e;
s->next = p->next;
p->next = s;
DataType temp = p->data;
p->data = s->data;
s->data = temp;
return head;
}
//前插操作其实用后插实现也可以,只需要传入i-1
//删除节点操作
//注意此删除的是链表第i个节点后的节点
void DeleteList(LinkList head, int i)
{
LinkList p,q;
p = Get(head, i - 1);
q = p->next;
p->next = q->next;
free(q);
}
//求表长操作
int Length(LinkList head)
{
LinkList p = head->next;
int j=0;
if (head->next == NULL)
{
printf("链表为空!");
return 0;
}
else
{
while (p != NULL)
{
++j;
p = p->next;
}
return j;
}
}
//销毁链表
void Free_List(LinkList head)
{
LinkList pointer;
while (head != NULL)
{
pointer = head;
head = head->next;
free(pointer);
}
}
int main()
{
//一定记得要初始化变量
LinkList *head = NULL, p;
p=Creat_list1(head);
TraverseList(p);
//这里的head与函数参数里的head不一样,传入后修改的是函数的head
//函数里head开辟链表头结点空间
//若是主函数里的head开辟空间,那么即使函数用void类型,也可改变链表
printf("\n后插\n");
Insert_back(p,9,1);//第三个参数不能<1
TraverseList(p);
//p的头结点空间早已开辟好,再插入操作,即使用函数void类型,也可改变链表
printf("\n前插\n");
Insert_front(p, 8, 2);//第三个参数不能<2
TraverseList(p);
printf("\n删除节点\n");
DeleteList(p, 1);
TraverseList(p);
printf("\n求表长\n");
int length = Length(p);
printf("length=%d\n",length);
printf("\n销毁链表\n");
Free_List(p);
return 0;
}