本节重点:
1.充分了解单链表的构建,增删改查
2.体验顺序表中元素如何进行操作
3.能灵活运用指针和引用进行编程
4.领会顺序表储存结构和掌握顺序表中各种基本运算算法设计
声明:
以下内容仅供学习,如有侵权,联系作者删除。
参考文献:数据结构上机实验指导p14
代码段展示:
第一部分
包含头文件定义,头插法建立尾插法建立链表:
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct LNode {
ElemType data;
struct LNode* next;//指向后继结点
}LinkNode;//声明单链表结点类型
//头插法建立单链表
void CreatListF(LinkNode*& L, ElemType a[], int n) {
LinkNode* s;
L = (LinkNode*)malloc(sizeof(LinkNode));//创建头结点
if (L) {
L->next = NULL;
for (int i = 0; i < n; i++) {
s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
if (s) {
s->data = a[i];
s->next = L->next;//将结点s插在原开始结点之前,头结点之后
L->next = s;
}
}
}
}
//尾插法建立单链表
void CreateListR(LinkNode*& L, ElemType a[], int n) {
LinkNode* s, * r;
L = (LinkNode*)malloc(sizeof(LinkNode));//创建头结点
if (L) {
L->next = NULL;
r = L;//r始终指向尾结点,开始时指向头结点
for (int i = 0; i < n; i++) {
s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
if (s) {
s->data = a[i];
r->next = s;//将结点s插入r结点之后
r = s;
}
}
r->next = NULL;//尾结点next域置为NULL
}
}
第二部分:
初始化线性表,销毁线性表以及判断线性表是否为空操作
//初始化线性表
void InitList(LinkNode*& L) {
L = (LinkNode*)malloc(sizeof(LinkNode));//创建头结点
if (L) {
L->next = NULL;//将单链表置为空表
}
}
//销毁线性表
void DestroyList(LinkNode*& L) {
LinkNode* pre = L, * p = pre->next;
while (p != NULL) {
free(pre);
pre = p;//将pre,p同步后移一个结点
p = pre->next;
}
free(pre);//此时p为NULL,pre指向尾结点,释放它
}
//判断线性表是否为空表
bool ListEmpty(LinkNode* L) {
return(L->next == NULL);
}
第三部分:
求线性表的长度,输出线性表,求单链表中第i个元素的值。
//求线性表的长度
int ListLength(LinkNode* L) {
int i = 0;
LinkNode* p = L;//p指向头结点,i置为0(即头结点序号为0)
while (p->next != NULL) {
i++;
p = p->next;
}
return(i);
}
//输出线性表
void DispList(LinkNode* L) {
LinkNode* p = L->next;//p指向首结点
while (p != NULL) {//p不为NULL,输出p结点的data域
printf("%c", p->data);
p = p->next;//p移向下一个结点
}
printf("\n");
}
//求线性表中第i个元素的值
bool GetList(LinkNode* L, int i, ElemType& e) {
int j = 0;
LinkNode* p = L;//p指向头结点,j置为0(即,头结点序号为0)
if (i <= 0) {
return false;//i错误,返回假
}
while (j < 1 && p != NULL) {//找到第i个结点p
j++;
p = p->next;
}
if (p == NULL) {//不存在第i个数据结点,返回假
return false;
}
else {//存在第i个结点,返回真
e = p->data;
return true;
}
}
第四部分:
查找,插入结点
//查找第一个值域为e的元素序号
int LocateElem(LinkNode* L, ElemType e) {
int i = 1;
LinkNode* p = L->next;//p指向首结点,i置为1(即首结点的序号为1)
while (p != NULL && p->data != e) {//查找data值为e的结点,其序号为i
p = p->next;
i++;
}
if (p == NULL)//不存在值为e的结点,返回0
return(0);
else
return(i);//存在值为e的结点
}
//插入第i个元素
bool ListInsert(LinkNode*& L, int i, ElemType e) {
int j = 0;
LinkNode* p = L, * s;//p指向头结点,j置为0(即头结点序号为0)
if (i <= 0) {
return false;//i错误返回假
}
//查找第i-1个结点p
while (j < i - 1 && p != NULL) {
j++;
p = p->next;
}
//未找到第i-1个结点,返回false
if (p == NULL) {
return false;
}
//找到第i-1个结点p,插入新结点并返回true
else {
s = (LinkNode*)malloc(sizeof(LinkNode));
if (s) {
s->data = e;//创建新结点s,其data域置为e
s->next = p->next;//将结点s插入到结点p之后
p->next = s;
}
return true;
}
}
第五部分:
删除元素操作
//删除第i个元素
bool ListDelete(LinkNode*& L, int i, ElemType& e) {
int j = 0;
LinkNode* p = L, * q;
if (i <= 0) {
return false;
}
while (j < i - 1 && p != NULL) {
j++;
p->next;
}
if (p == NULL) {
return false;
}
else {
q = p->next;
if (q == NULL) {
return false;
}
e = q->data;
p->next = q->next;
free(q);
return true;
}
}
主函数部分:
int main() {
LinkNode* h;
ElemType e;
printf("单链表的基本操作如下:\n");
printf("(1)初始化单链表h\n");
InitList(h);
printf("(2)依次采用尾插法插入a,b,c,d,e元素\n");
ListInsert(h, 1, 'a');
ListInsert(h, 2, 'b');
ListInsert(h, 3, 'c');
ListInsert(h, 4, 'd');
ListInsert(h, 5, 'e');
printf("(3) 输出单链表h:");
DispList(h);
printf("(4) 单链表h长度:%d\n", ListLength(h));
printf("(5) 单链表h为%s\n", (ListEmpty(h) ? "空" : "非空"));
GetList(h, 3, e);
printf("(6) 单链表h的第三个元素:%c\n", e);
printf("(7) 元素a的位置:%d\n", LocateElem(h, 'a'));
printf("(8) 在第四个元素位置上插入f元素\n");
ListInsert(h, 3, e);
printf("(9) 输出单链表h:");
DispList(h);
printf("(10) 删除h的第三个元素\n");
ListDelete(h, 3, e);
printf("(11) 输出单链表h:");
DispList(h);
printf("(12) 释放单链表h\n");
DestroyList(h);
return 1;
}