#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;//有效数据域
struct LNode *next;//下一个结点的地址
}LNode;
typedef LNode* LinkList;//引用链表的参数是头指针,所以把结点型地址命名为LinkList
//建立空表:为头结点分配内存,头结点的地址域为空
void InitList(LinkList *L)
{
*L = (LNode*)malloc(sizeof(LNode));//为头结点分配内存,地址返回链表的头指针
if(*L==NULL) exit(-1);//动态分配内存必须检测返回地址判断是否成功分配
(*L)->next = NULL;//头结点地址域为NULL
}
//销毁单向链表:free(头结点和表头到表尾的所有结点的地址)
void DestroyList(LinkList *L)
{
LNode* p;
while(*L)
{
p = (*L)->next;
free(*L);//free(p):释放p指向的内存,归还给操作做系统。
*L = p; //p变量仍存在,仍旧指向已经恢复自由的原先内存,一般还需要让p=NULL
}
}
//清空单链表:free(表头和表尾的所有结点,保留头结点并使其地址域为NULL)
void ClearList(LinkList *L)
{
LNode*q,*p = (*L)->next;//指向表头,而不是头结点
while(p)
{
q = p;
free(p);
p = q;
}
(*L)->next = NULL;
}
//判断单项链表是否为空
bool EmptyList(LinkList L)
{
return L->next?false:true;
}
//返回单向链表的长度
int LengthList(LinkList L)
{
LNode* p = L->next;
int i = 0;//计数器
while(p)//数据流
{
i++;
p = p->next;
}
return i;
}
//得到链表某个位置的结点值
bool GetElem(LinkList L,int i,ElemType* e)
{//1<=i<=length
if(i<1)
{
printf("i的值不合理!\n");
return false;
}
int j = 0;
LNode* p = p->next;
while(p&&j<i-1)//检测i是否>length
{
p = p->next;
j++;
}
if(!p)//pls+1状态是每个循环结束后的最终状态值
{
printf("i的值不合理!\n");
return false;
}
*e = p->data;
return true;
}
//在第i个位置前插入新结点:i<=i<=length+1
bool InsertList(LinkList L,int i,ElemType e)
{//寻找第i-1个结点,满足0<=i-1<=length,i的值自然合理
if(i-1<0)
{
printf("i的值不合理!\n");
return false;
}
LNode*p = L;//指向头结点
int j = 0;
while(p&&j<i-1)//有两种理解方式:数据流,流下一个计数一次,流i-1次停止
{ //p切换指i-1次,直到p指向最后一个结点后停止
p = p->next;
j++;
}
if(!p)
{
printf("i的值不合理!\n");
return false;
}//p指向第i-1个结点
LNode* q;
q = (LNode*)malloc(sizeof(LNode));//构建要插入的新结点
q->data = e;
q->next = p->next;//新节点保存第i个的地址
p->next = q;//第i-1个结点保存新结点的地址
return true;
}
//删除某个位置的结点:1<=i<=length
bool DeleteList(LinkList L,int i,ElemType *e)
{//寻找第i-1个结点 0<=i<=length-1
if(i-1<0)
{
printf("i的值不合理!\n");
return false;
}
LNode* p = L;
int j = 0;
while(p&&j<i-1)
{
p = p->next;
j++;
}
if(!p||p->next==NULL)//pls+1或指向最后一个结点说明i值不合理
{
printf("i的值不合理!\n");
return false;
}
p->next = p->next->next;
return true;
}
int LocateList(LinkList L,ElemType e)
{
int i = 1;
LNode*p = L->next;
while(p)//数据流
{
if(p->data==e)
return i;
p = p->next;//满足切换下一个数据的要求,如果p=p->next->next,是跳跃切换
i++;
}
if(!p)
return 0;
}
void TraverseList(LinkList L)
{
LNode* p = L->next;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
// 输入n个元素的值,依次插在表头,建立带头结点结构的单向链表L
void CreateList(LinkList *L,int n)
{
int i;
LinkList p;
*L=(LinkList)malloc(sizeof(struct LNode));
(*L)->next=NULL; //为头结点分配内存
printf("请输入%d个数据\n",n);
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(struct LNode));
scanf("%d",&p->data);
p->next=(*L)->next;
(*L)->next=p;
}
}
//输入n个元素的值,依次插在表尾,建立带表头结构的单链线性表
void CreateList2(LinkList *L,int n)
{
int i;
LinkList p,q;
*L=(LinkList)malloc(sizeof(struct LNode)); // 生成头结点
(*L)->next=NULL;
q=*L;//q指向表尾
printf("请输入%d个数据\n",n);
for(i=1;i<=n;i++)
{
p=(LinkList)malloc(sizeof(struct LNode));
scanf("%d",&p->data);
q->next=p;
q=q->next;//q始终指向表尾
}
p->next=NULL;
}
//已知单向链表La和Lb的元素按值非递减排列。
//归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
void MergeList(LinkList La,LinkList *Lb,LinkList *Lc)
{
LinkList pa=La->next,pb=(*Lb)->next,pc;
*Lc=pc=La;
while(pa&&pb)
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
pc->next=pa?pa:pb;
free(*Lb);
Lb=NULL;
}
/********************************************************************
int main()//测试MergeList
{
int n=5;
LinkList La,Lb,Lc;
printf("按非递减顺序, ");
CreateList2(&La,n); // 正位序输入n个元素的值
printf("La=");
TraverseList(La);
printf("按非递增顺序, ");
CreateList(&Lb,n);
printf("Lb=");
TraverseList(Lb);
MergeList(La,&Lb,&Lc);
printf("Lc=");
TraverseList(Lc);
return 0;
}
************************************************************/
int main()
{
LinkList L;
ElemType e;
InitList(&L);
int i;
for(i=1;i<5;i++)
{
InsertList(L,i,i);
}
printf("遍历单向链表\n");
TraverseList(L);
printf("在第5个位置插入11\n");
InsertList(L,5,11);
printf("遍历单向链表\n");
TraverseList(L);
printf("在第7个位置插入100\n");
InsertList(L,7,100);
printf("遍历单向链表\n");
TraverseList(L);
printf("删除第6个位置结点\n");
DeleteList(L,6,&e);
printf("遍历单向链表\n");
TraverseList(L);
printf("删除第0个位置结点\n");
DeleteList(L,0,&e);
printf("遍历单向链表\n");
TraverseList(L);
DeleteList(L,5,&e);
printf("遍历单向链表\n");
TraverseList(L);
}
先找到课本,熟悉单向链表的结构; 关键词: 头结点,头指针,表头,表尾,数据域,地址域(指针域)
1,生成空表销毁链表 2,清空链表 3,是否为空表 4,表长 5,查找第i个结点的值
6,查找第一个等于e的结点在链表的位置 7,插入 8,删除 9,遍历 10,正序插入结点到单链表 11,逆序插入结点到单链表 12,将两个有序链表合并成一个有序链表
13,测试10,11,12的MAIN函数 14,测试1-9的MAIN函数
练习题 (1)合并La,Lb,去掉重复结点
(2)排序单向链表
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;//有效数据域
struct LNode *next;//下一个结点的地址
}LNode;
typedef LNode* LinkList;//引用链表的参数是头指针,所以把结点型地址命名为LinkList
//建立空表:为头结点分配内存,头结点的地址域为空
void InitList(LinkList *L)
{
*L = (LNode*)malloc(sizeof(LNode));//为头结点分配内存,地址返回链表的头指针
if(*L==NULL) exit(-1);//动态分配内存必须检测返回地址判断是否成功分配
(*L)->next = NULL;//头结点地址域为NULL
}
//销毁单向链表:free(头结点和表头到表尾的所有结点的地址)
void DestroyList(LinkList *L)
{
LNode* p;
while(*L)
{
p = (*L)->next;
free(*L);//free(p):释放p指向的内存,归还给操作做系统。
*L = p; //p变量仍存在,仍旧指向已经恢复自由的原先内存,一般还需要让p=NULL
}
}
//清空单链表:free(表头和表尾的所有结点,保留头结点并使其地址域为NULL)
void ClearList(LinkList *L)
{
LNode*q,*p = (*L)->next;//指向表头,而不是头结点
while(p)
{
q = p;
free(p);
p = q;
}
(*L)->next = NULL;
}
//判断单项链表是否为空
bool EmptyList(LinkList L)
{
return L->next?false:true;
}
//返回单向链表的长度
int LengthList(LinkList L)
{
LNode* p = L->next;
int i = 0;//计数器
while(p)//数据流
{
i++;
p = p->next;
}
return i;
}
//得到链表某个位置的结点值
bool GetElem(LinkList L,int i,ElemType* e)
{//1<=i<=length
if(i<1)
{
printf("i的值不合理!\n");
return false;
}
int j = 0;
LNode* p = p->next;
while(p&&j<i-1)//检测i是否>length
{
p = p->next;
j++;
}
if(!p)//pls+1状态是每个循环结束后的最终状态值
{
printf("i的值不合理!\n");
return false;
}
*e = p->data;
return true;
}
//在第i个位置前插入新结点:i<=i<=length+1
bool InsertList(LinkList L,int i,ElemType e)
{//寻找第i-1个结点,满足0<=i-1<=length,i的值自然合理
if(i-1<0)
{
printf("i的值不合理!\n");
return false;
}
LNode*p = L;//指向头结点
int j = 0;
while(p&&j<i-1)//有两种理解方式:数据流,流下一个计数一次,流i-1次停止
{ //p切换指i-1次,直到p指向最后一个结点后停止
p = p->next;
j++;
}
if(!p)
{
printf("i的值不合理!\n");
return false;
}//p指向第i-1个结点
LNode* q;
q = (LNode*)malloc(sizeof(LNode));//构建要插入的新结点
q->data = e;
q->next = p->next;//新节点保存第i个的地址
p->next = q;//第i-1个结点保存新结点的地址
return true;
}
//删除某个位置的结点:1<=i<=length
bool DeleteList(LinkList L,int i,ElemType *e)
{//寻找第i-1个结点 0<=i<=length-1
if(i-1<0)
{
printf("i的值不合理!\n");
return false;
}
LNode* p = L;
int j = 0;
while(p&&j<i-1)
{
p = p->next;
j++;
}
if(!p||p->next==NULL)//pls+1或指向最后一个结点说明i值不合理
{
printf("i的值不合理!\n");
return false;
}
p->next = p->next->next;
return true;
}
int LocateList(LinkList L,ElemType e)
{
int i = 1;
LNode*p = L->next;
while(p)//数据流
{
if(p->data==e)
return i;
p = p->next;//满足切换下一个数据的要求,如果p=p->next->next,是跳跃切换
i++;
}
if(!p)
return 0;
}
void TraverseList(LinkList L)
{
LNode* p = L->next;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
// 输入n个元素的值,依次插在表头,建立带头结点结构的单向链表L
void CreateList(LinkList *L,int n)
{
int i;
LinkList p;
*L=(LinkList)malloc(sizeof(struct LNode));
(*L)->next=NULL; //为头结点分配内存
printf("请输入%d个数据\n",n);
for(i=n;i>0;--i)
{
p=(LinkList)malloc(sizeof(struct LNode));
scanf("%d",&p->data);
p->next=(*L)->next;
(*L)->next=p;
}
}
//输入n个元素的值,依次插在表尾,建立带表头结构的单链线性表
void CreateList2(LinkList *L,int n)
{
int i;
LinkList p,q;
*L=(LinkList)malloc(sizeof(struct LNode)); // 生成头结点
(*L)->next=NULL;
q=*L;//q指向表尾
printf("请输入%d个数据\n",n);
for(i=1;i<=n;i++)
{
p=(LinkList)malloc(sizeof(struct LNode));
scanf("%d",&p->data);
q->next=p;
q=q->next;//q始终指向表尾
}
p->next=NULL;
}
//已知单向链表La和Lb的元素按值非递减排列。
//归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
void MergeList(LinkList La,LinkList *Lb,LinkList *Lc)
{
LinkList pa=La->next,pb=(*Lb)->next,pc;
*Lc=pc=La;
while(pa&&pb)
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
pc->next=pa?pa:pb;
free(*Lb);
Lb=NULL;
}
/********************************************************************
int main()//测试MergeList
{
int n=5;
LinkList La,Lb,Lc;
printf("按非递减顺序, ");
CreateList2(&La,n); // 正位序输入n个元素的值
printf("La=");
TraverseList(La);
printf("按非递增顺序, ");
CreateList(&Lb,n);
printf("Lb=");
TraverseList(Lb);
MergeList(La,&Lb,&Lc);
printf("Lc=");
TraverseList(Lc);
return 0;
}
************************************************************/
int main()
{
LinkList L;
ElemType e;
InitList(&L);
int i;
for(i=1;i<5;i++)
{
InsertList(L,i,i);
}
printf("遍历单向链表\n");
TraverseList(L);
printf("在第5个位置插入11\n");
InsertList(L,5,11);
printf("遍历单向链表\n");
TraverseList(L);
printf("在第7个位置插入100\n");
InsertList(L,7,100);
printf("遍历单向链表\n");
TraverseList(L);
printf("删除第6个位置结点\n");
DeleteList(L,6,&e);
printf("遍历单向链表\n");
TraverseList(L);
printf("删除第0个位置结点\n");
DeleteList(L,0,&e);
printf("遍历单向链表\n");
TraverseList(L);
DeleteList(L,5,&e);
printf("遍历单向链表\n");
TraverseList(L);
}