/*
带头结点的单链表的常用操作
说明:本版本在 main 函数里加入了 InitFlag 变量,用以识别传递的实参链表未初始化时的野指针问题。正常的操作时,这种情况应尽量避免,本版本没有刻意在操作里增加参数 InitFlag,目的是让操作更纯粹一些。在操作里加入,则操作的参数合法性审核会更健壮。根据需要选择吧。
1、链队初始化,初始化一个只含头结点的空单链表 L
Status InitList_L (LinkList &L) ;
2、构造单链表结点
LNode* MakeNode_L(ElemType e);
3、销毁单链表
Status DestroyList_L(LinkList &L) ;
4、判断单链表是否为空
Status ListEmpty_L(LinkList L);
5、清空单链表
Status ClearList_L(LinkList &L);
6、单链表的插入 P 的后继结点操作
Status InsertAfter_L(LNode *p, LNode *q);
7、头插法往单链表中的插入一个结点
Status InsertFirst_L(LinkList &L, ElemType e);
8、删除单链表的第 i 个结点
Status ListDelete(LinkList &L,int i,ElemType &e);
9、单链表的查找元素操作
LNode* Search_L(LinkList L, ElemType e);
10、在有序单链表中查找插入位置
LNode* SearchPosition_L(LinkList L, ElemType e);
11、在有序表中的正确位置插入结点 e
Status InsertNode_L(LinkList &L, ElemType e);
12、求链表的长度
Status GetListLength_L(LinkList L);
13、遍历单链表
Status ListTraverse_L(LinkList L, Status(*visit)(ElemType e));
14、配合遍历,依次输出表中元素
Status PrintList_L(ElemType e);
15、读取单链表中指定位置的元素
Status GetPosElem_L(LinkList L, int pos, ElemType &e);
*/
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define PERROR -2
typedef int Status;
// 数据元素的类型,使用时需根据问题的需求定义。
typedef int ElemType;
// 结单链表点类型定义
typedef struct LNode {
ElemType data; // 数据域
struct LNode *next; // 指针域
} LNode;
// 链表结构体类型定义
typedef LNode* LinkList;
// 1、链队初始化,初始化一个只含头结点的空单链表 L
Status InitList_L (LinkList &L) {
L = (LNode*)malloc(sizeof(struct LNode)); // 为头结点申请空间
if(L == NULL) return OVERFLOW; //如果申请失败,返回溢出
L->next = NULL;
return OK;
}
// 2、构造单链表结点
LNode* MakeNode_L(ElemType e) {
LNode *p;
p = (LNode*)malloc(sizeof(struct LNode)); // 分配结点空间
if (p!=NULL) {
p->data = e;
p->next = NULL;
}
return p;
}
// 3、销毁单链表
Status DestroyList_L(LinkList &L){
LNode *q;
if(L==NULL) return ERROR; // 判断链表是否存在,已销毁,不再执行销毁操作。
while(L!=NULL) { // 如果是非空表,依次释放表中各结点
q = L;
L = q->next;
free(q);
}
return OK;
}
// 4、判断单链表是否为空
Status ListEmpty_L(LinkList L){
if(NULL == L) return ERROR; // 判断链表是否存在,已销毁,不再执行销毁操作。
if(L->next == NULL){
return TRUE;
}
else{
return FALSE;
}
}
// 5、清空单链表
Status ClearList_L(LinkList &L){
if( L==NULL )return PERROR; // 参数合法性检验,非法返回参数错误
L->next = NULL; // 将头结点的指针域置空
return OK;
}
// 6、单链表的插入 P 的后继结点操作
Status InsertAfter_L(LNode *p, LNode *q){
if(p == NULL || q == NULL) return PERROR; // 参数不合理
q->next = p->next; // 修改q结点的指针域
p->next = q;
return OK;
}
// 7、头插法往单链表中的插入一个结点
Status InsertFirst_L(LinkList &L, ElemType e){
if(L == NULL) return PERROR; // 参数不合理
LNode *p;
p = MakeNode_L(e);
if(p == NULL)return ERROR; // 内存溢出,结点创建不成功,不能执行插入操作
p->next = L->next; // 修改q结点的指针域
L->next = p;
return OK;
}
// 8、删除单链表的第 i 个结点
Status ListDelete(LinkList &L,int i,ElemType &e){
LNode *p, *q;
p = L;
int j = 0;
while(p!=NULL && j<i-1){ // 如果存在,找到第 i-1 个结点
p = p->next;
j++;
}
if(p==NULL||p->next==NULL)return ERROR; // 如果第 i-1 个结点和第 i 个结点不存在,无法删除,返回错误
q = p->next; // 用指针 q 指向第 i 个结点
e = q->data; // 将第 i 个结点的值赋给 e
p->next = q->next; // 将 q 的后继赋值给 p
free(q); // 释放结点 q 所占空间
return OK;
}
// 9、单链表的查找元素操作
LNode* Search_L(LinkList L, ElemType e) {
LNode *p;
if(L == NULL) return NULL;
p = L->next;
while(p!=NULL && p->data != e) {
p = p->next; // 访问下一个元素
}
return p;
}
// 10、在有序单链表中查找插入位置
LNode* SearchPosition_L(LinkList L, ElemType e) {
LNode *p, *q;
if(L == NULL) return NULL;
p = L; // p 用来保存插入位置的前一个结点
q = p->next; // q 指向插入点对应的结点,即在插入点之前插入 e
while(q!=NULL && q->data<e) {
p = q; // 寻找向后继续进行,p、q 均向后移动
q = p->next; // 访问下一个元素
}
return p;
}
// 11、在有序表中的正确位置插入结点 e
Status InsertNode_L(LinkList &L, ElemType e){
if(L == NULL) return PERROR; // 参数不合理
LNode *p, *q;
q = MakeNode_L(e);
if(p = NULL)return ERROR; // 内存溢出,结点创建不成功,不能执行插入操作
p = SearchPosition_L(L, e);
q->next = p->next; // 修改q结点的指针域
p->next = q;
return OK;
}
// 12、求链表的长度
Status GetListLength_L(LinkList L) {
int length = 0;
LNode *p;
if(L == NULL) return PERROR; // 参数不合理
if(L->next == NULL)return 0;
p = L->next;
while(p!=NULL){
length++;
p = p->next;
}
return length;
}
// 13、遍历单链表
Status ListTraverse_L(LinkList L, Status(*visit)(ElemType e)) {
if(L == NULL) return PERROR; // 参数不合理
if(L->next == NULL)return ERROR; // 空表不执行操作
LNode *p;
p = L->next;
while (p != NULL) {
visit(p->data);
p = p->next;
}
return OK;
}
// 14、配合遍历,依次输出表中元素
Status PrintList_L(ElemType e){
printf("%d\t",e);
return OK;
}
// 15、读取单链表中指定位置的元素
Status GetPosElem_L(LinkList L, int pos, ElemType &e){
if(L == NULL) return PERROR; // 参数不合理
if(L->next == NULL)return ERROR; // 空表不执行操作
if(pos<=0) return PERROR; // 参数不合理
int i = 1;
LNode *p;
p = L->next;
while(i!=pos){
if(p->next == NULL) return ERROR; // 指定位置超出了单链表的长度
p = p->next;
i++;
}
e = p->data;
return OK;
}
int main(){
int i, e, state;
int InitFlag = FALSE;
LinkList L;
printf("1.初始化单链表\n");
printf("2.销毁单链表\n");
printf("3.判断单链表是否为空\n");
printf("4.清空单链表\n");
printf("5.将元素插入在表头\n");
printf("6.从线性表中删除表头元素\n");
printf("7.打印线性表中的所有元素\n");
do{
printf("请输入你要进行的操作:\n");
scanf("%d",&i);
switch(i){
case 1 :
state = InitList_L(L);
if(state == OK){
InitFlag = TRUE;
printf("单链表初始化成功。\n");
}else{
printf("单链表初始化失败!\n");
}
break;
case 2 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
state = DestroyList_L(L);
if(state == ERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else{
InitFlag = FALSE;
printf("单链表销毁成功。\n");
}
}
break;
case 3 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
state = ListEmpty_L(L);
if(state == PERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else if(state == TRUE){
printf("单链表为空!\n");
}else if(state == FALSE){
printf("单链表不为空!\n");
}
}
break;
case 4 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
state = ClearList_L(L);
if(state == PERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else{
printf("已为您清空单链表。\n");
}
}
break;
case 5 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
printf("请输入将要利用头插法加入单链表的元素的值:\n");
scanf("%d",&e);
state = InsertFirst_L(L, e);
if(state == PERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else if(state == OK){
printf("元素 %d 成功加入单链表。\n",e);
}else{
printf("元素 %d 加入单链表失败!\n",e);
}
}
break;
case 6 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
state = ListDelete( L, 1, e);
if(state == PERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else if(state == OK){
printf("表头元素 %d 成功从单链表里删除!\n",e);
}else{
printf("单链表中没有元素,不能执行删除元素操作!\n");
}
}
break;
case 7 :
if(InitFlag == FALSE){
printf("单链表不存在或已被销毁!\n");
}else{
state = ListTraverse_L(L, PrintList_L);
if(state == PERROR){
printf("请确认参数合法化或者先执行单链表的初始化操作!\n");
}else if(state == OK){
printf("链表中的元素已成功输出。\n");
}else{
printf("单链表中没有元素!\n");
}
}
break;
}
}while(i>=1&&i<=7);
return 0;
}