目录
格式
头文件
宏定义
线性表的单链表存储结构
按位查找
插入元素
删除元素
头插法建立单链表
合并非递减单链表
其他基本操作
完整版
测试代码(主函数)
测试结果
格式
参考 2.3节 线性表的链式表示和实现
头文件
宏定义
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstring>#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;
线性表的单链表存储结构
//-----线性表的单链表存储结构-----
typedef struct LNode {ElemType data;struct LNode* next;
}LNode,*LinkList;
按位查找
//算法2.8 函数GetElem在单链表中的实现。
Status GetElem_L(LinkList L, int i, ElemType& e) {//L为带头结点的单链表的头指针。//当第i个元素存在时,其值赋给e并返回OK,否则返回ERRORLinkList p = L->next;int j = 1;//初始化,p指向第一个结点,j为计数器while (p && j < i) {//顺指针向后查找,直到p指向第i个元素或p为空p = p->next;++j;}if (!p || j > i)return ERROR;//第i个元素不存在e = p->data;//取第i个元素return OK;
}
插入元素
//算法2.9 函数ListInsert在单链表中的实现
Status ListInsert_L(LinkList& L, int i, ElemType e) {//在带头结点的单链线性表L中第i个位置之前插入元素eLinkList p = L;int j = 0;while (p && j < i - 1) {p = p->next;++j;//寻找第i-1个结点}if (!p || j > i - 1)return ERROR;//i小于1或者大于表长+1LinkList s = (LinkList)malloc(sizeof(LNode));//生成新结点s->data = e;s->next = p->next;//插入L中p->next = s;
}
删除元素
//算法2.10 函数ListDelete在单链表中的实现
Status ListDelete_L(LinkList& L, int i, ElemType& e) {//在带头结点的单链线性表L中,删除第i个元素,并由e返回其值LinkList p = L;int j = 0;while (p && j < i - 1) {p = p->next;++j;//寻找第i个结点,p->next所在的位置}if (!(p->next) || j > i - 1)return ERROR;//删除位置不合理LinkList q = p->next;p->next = q->next;//删除并释放结点e = q->data;free(q);return OK;
}
头插法建立单链表
//算法2.11 头插法建立单链表
void CreateList_L(LinkList& L, int n) {//逆位序输入n个元素的值,建立带表头结点的单链线性表L。L = (LinkList)malloc(sizeof(LNode));L->next = NULL;//先建立一个带头结点的单链表LinkList p;for (int i = n;i > 0;i--) {p = (LinkList)malloc(sizeof(LNode));scanf_s("%d", &p->data);//输入元素值p->next = L->next;//插入到表头L->next = p;//插入到表尾// LinkList T=L;// for循环,用下面三行替换插入表头两行//p->next=NULL;//T->next=p;//T=p;}
}
合并非递减单链表
//算法2.12 合并非递减单链表
void MergeList_L(LinkList& La, LinkList& Lb, LinkList& Lc) {//已知顺序线性表La和Lb的元素按值非递减排列//归并La和Lb得到的新的顺序线性表Lc,Lc的元素也按值非递减排列LinkList pa = La->next;LinkList pb = Lb->next;LinkList pc = Lc = La;//用La的头结点作为Lc的头结点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的头结点
}
free函数不能放在while循环内,否则会出现以下情况。
警告信息:使用未初始化的内存"Lb"。
看不懂,但这个问题解决了。
其他基本操作
void PrintList_L(LinkList L) {//打印链表LinkList p = L->next;while (p) {//while(p=p->next)这样写行吗?printf("%d ", p->data);p = p->next;}printf("\n");
}Status DestroyList_L(LinkList& L) {//销毁链表LinkList p;while (L) {p = L;L = L->next;free(p);//free函数的释放是只释放一个结点,还是释放后面相关的所有结点?--已解决,只释放一个结点。}return OK;
}
完整版
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstring>#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int ElemType;//-----线性表的单链表存储结构-----
typedef struct LNode {ElemType data;struct LNode* next;
}LNode,*LinkList;//算法2.11 头插法建立单链表
void CreateList_L(LinkList& L, int n) {//逆位序输入n个元素的值,建立带表头结点的单链线性表L。L = (LinkList)malloc(sizeof(LNode));L->next = NULL;//先建立一个带头结点的单链表LinkList p;for (int i = n;i > 0;i--) {p = (LinkList)malloc(sizeof(LNode));scanf_s("%d", &p->data);//输入元素值p->next = L->next;//插入到表头L->next = p;//插入到表尾// LinkList T=L;// for循环,用下面三行替换插入表头两行//p->next=NULL;//T->next=p;//T=p;}
}//算法2.8 函数GetElem在单链表中的实现。
Status GetElem_L(LinkList L, int i, ElemType& e) {//L为带头结点的单链表的头指针。//当第i个元素存在时,其值赋给e并返回OK,否则返回ERRORLinkList p = L->next;int j = 1;//初始化,p指向第一个结点,j为计数器while (p && j < i) {//顺指针向后查找,直到p指向第i个元素或p为空p = p->next;++j;}if (!p || j > i)return ERROR;//第i个元素不存在e = p->data;//取第i个元素return OK;
}//算法2.9 函数ListInsert在单链表中的实现
Status ListInsert_L(LinkList& L, int i, ElemType e) {//在带头结点的单链线性表L中第i个位置之前插入元素eLinkList p = L;int j = 0;while (p && j < i - 1) {p = p->next;++j;//寻找第i-1个结点}if (!p || j > i - 1)return ERROR;//i小于1或者大于表长+1LinkList s = (LinkList)malloc(sizeof(LNode));//生成新结点s->data = e;s->next = p->next;//插入L中p->next = s;
}//算法2.10 函数ListDelete在单链表中的实现
Status ListDelete_L(LinkList& L, int i, ElemType& e) {//在带头结点的单链线性表L中,删除第i个元素,并由e返回其值LinkList p = L;int j = 0;while (p && j < i - 1) {p = p->next;++j;//寻找第i个结点,p->next所在的位置}if (!(p->next) || j > i - 1)return ERROR;//删除位置不合理LinkList q = p->next;p->next = q->next;//删除并释放结点e = q->data;free(q);return OK;
}//算法2.12 合并非递减单链表
void MergeList_L(LinkList& La, LinkList& Lb, LinkList& Lc) {//已知顺序线性表La和Lb的元素按值非递减排列//归并La和Lb得到的新的顺序线性表Lc,Lc的元素也按值非递减排列LinkList pa = La->next;LinkList pb = Lb->next;LinkList pc = Lc = La;//用La的头结点作为Lc的头结点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的头结点
}void PrintList_L(LinkList L) {//打印链表LinkList p = L->next;while (p) {//while(p=p->next)这样写行吗?printf("%d ", p->data);p = p->next;}printf("\n");
}Status DestroyList_L(LinkList& L) {//销毁链表LinkList p;while (L) {p = L;L = L->next;free(p);//free函数的释放是只释放一个结点,还是释放后面相关的所有结点?--已解决,只释放一个结点。}return OK;
}
测试代码(主函数)
#include "LinkList.h"int main()
{LinkList La = NULL,Lb = NULL,Lc = NULL;int n1,n2;Status i = 0;ElemType e;//变量声明//测试算法2.11printf("请输入元素个数:");//构建单链表Lascanf_s("%d", &n1);printf("请输入元素:");CreateList_L(La, n1);printf("\n");printf("头插法得到的元素逆序:");PrintList_L(La);//测试算法2.8i = GetElem_L(La, 3, e);if (i)printf("第3个元素为%d\n", e);elseprintf("第3个元素不存在\n");//测试算法2.9,2.10.i = ListInsert_L(La, 3, 3);if (i)printf("插入成功\n");elseprintf("插入失败\n");i = ListDelete_L(La, 5, e);if (i)printf("删除成功\n");elseprintf("删除失败\n");//测试算法2.12printf("请输入元素个数:");//构建单链表Lbscanf_s("%d", &n2);printf("请输入元素:");CreateList_L(Lb, n2);printf("\n");printf("头插法得到的元素逆序:");PrintList_L(Lb);MergeList_L(La, Lb, Lc);printf("新链表的元素:");PrintList_L(Lc);DestroyList_L(Lc);//因为Lc实质是La和Lb的合并,而且Lb的头结点已经被释放了。return 0;
}