3.1 单链表
3.1.1 定义
-
注:
元素离散的分布在存储空间中,所以单链表是非随机存取的存储结构。
即不能直接找到表中某个特定的结点,需要从表头开始遍历,依次查找。
-
定义的代码
typedef struct LNode { ElemType data;//每个节点存放一个数据元素 struct LNode* next;//指向下一个节点 }LNode,*LinkList;
-
头结点和头指针
-
初始化
分为带或不带头结点的初始化。
一般用带头结点的链表,会使后续操作方便。
-
不带头结点的初始化
bool InitList(LinkList &L) { L=NULL; return ture; }
-
带头结点的初始化
bool InitList(LinkList& L) { L = (LNode*)malloc(sizeof(LNode));//分配一个头节点 if (L == NULL)return false;//分配失败 L->next = NULL; return true; }
-
3.1.2 建立
1)头插法建立单链表
在链表表头插入新结点。
-
步骤
1.将要插入结点的指针指向 原第一个结点;
2.将头结点指针指向 要插入的结点。
//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
LNode* s;
int x;
InitList(L);//初始化
scanf_s("%d", &x);//输入结点值
//插入表中
while (x != 9999)//9999表示结束
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;//新结点指针域指向原来的第一个结点
//头结点指向新结点
L->next = s;
scanf_s("%d", &x);
}
return L;
}
2)尾插法建立单链表
在链表末尾插入新结点。
-
步骤
1.将尾结点的指针指向新结点;
2.更新尾指针(新尾指针变成新结点)。
//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
LNode* s, * r = L;//r为表尾指针
int x;
scanf_s("%d", &x);//输入结点值
//插入表中
while (x != 9999)//9999表示结束
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
//表尾指针指向新结点
r->next = s;
//更新表尾结点
r = s;
scanf_s("%d", &x);
}
r->next = NULL;//尾结点指针置空
return L;
}
3.1.3 插入
-
步骤
1.查找插入位置的前驱结点;
2.将插入结点的指针 指向 插入位置的后驱结点;
3.将前驱结点的指针指向 插入结点。
//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
if (i < 1)return false;
LNode* p;//指针指向当前扫描到的节点
int j = 0;//当前p指向的是第几个节点
//查找第i个位置
p = L;//L指向头节点,头节点是第0个节点
while(p!=NULL&&j<i-1)
{
p = p->next;
j++;
}
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
3.1.4 删除
- 步骤
bool ListDelete(LinkList& L, int i, ElemType& e)
{
if (i < 1)return false;
LNode* p;//指针p指向当前扫描到的结点
int j = 0;//当前p指向的是第几个结点
//循环找到第i-1个结点
p = L;//指向头结点
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
//i值不合法
if (p == NULL||p->next==NULL)return false;
LNode* q = p->next;//令q指向被删除结点
e = q->data;//用e返回元素的值
p->next = q->next;//将*q结点从链中断开
free(q);//释放结点存储空间
return true;
}
3.1.5 查找
1)按序号查找结点
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
if (i < 1)return NULL;
int j = 1;
LNode* p = L->next;//第1个结点指针赋给p
while (p != NULL && j < i)
{
p = p->next;
j++;
}
return p;
}
2)按值查找结点
//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
LNode* p = L->next;
while (p != NULL && p->data != e)
{
p = p->next;
}
return p;
}
* 完整代码
#include<stdio.h>
#include <malloc.h>
#include<time.h>//用于生成随机数
#include<stdlib.h>
#define ElemType int
//---------------定义---------------
typedef struct LNode
{
ElemType data;//每个节点存放一个数据元素
struct LNode* next;//指向下一个节点
}LNode,*LinkList;
初始化不带头节点的单链表
//bool InitList(LinkList& L) {
// L = NULL;
// return true;
//}
不带会麻烦
//初始化带头节点的单链表
bool InitList(LinkList& L)
{
L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
if (L == NULL)return false;
L->next = NULL;
return true;
}
//---------------建立单链表---------------
//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
int m;
printf("\n1.手动输入\n2.自动生成\n");
scanf_s("%d", &m);
if (m == 1)
{
LNode* s;
int x;
scanf_s("%d", &x);//输入结点值
//插入表中
while (x != 9999)//9999表示结束
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;//新结点指针域指向原来的第一个结点
//头结点指向新结点
L->next = s;
scanf_s("%d", &x);
}
return L;
}
else if (m == 2)
{
LNode* s;
int n = 10;//结点个数
srand(time(0));//初始化随机数种子
while (n--)
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = rand() % 100 + 1;//随机产生100以内的数
s->next = L->next;
L->next = s;
}
}
else
{
printf("请重新输入!\n");
List_HeadInsert(L);
}
}
//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
int m;
printf("\n1.手动输入\n2.自动生成\n");
scanf_s("%d", &m);
if (m == 1)
{
LNode* s, * r = L;//r为表尾指针
int x;
scanf_s("%d", &x);//输入结点值
//插入表中
while (x != 9999)//9999表示结束
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
//表尾指针指向新结点
r->next = s;
//更新表尾结点
r = s;
scanf_s("%d", &x);
}
r->next = NULL;//尾结点指针置空
return L;
}
else if (m == 2)
{
LNode* s,*r=L;
int n = 10;//结点个数
srand(time(0));//初始化随机数种子
while (n--)
{
//创建新结点
s = (LNode*)malloc(sizeof(LNode));
s->data = rand() % 100 + 1;//随机产生100以内的数
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
else
{
printf("请重新输入!\n");
List_TailInsert(L);
}
}
//---------------插入-----------------
//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
if (i < 1)return false;
LNode* p;//指针指向当前扫描到的节点
int j = 0;//当前p指向的是第几个节点
//查找第i个位置
p = L;//L指向头节点,头节点是第0个节点
while(p!=NULL&&j<i-1)
{
p = p->next;
j++;
}
if (p == NULL)
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//---------------删除----------------
bool ListDelete(LinkList& L, int i, ElemType& e)
{
if (i < 1)return false;
LNode* p;//指针p指向当前扫描到的结点
int j = 0;//当前p指向的是第几个结点
//循环找到第i-1个结点
p = L;//指向头结点
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
//i值不合法
if (p == NULL||p->next==NULL)return false;
LNode* q = p->next;//令q指向被删除结点
e = q->data;//用e返回元素的值
p->next = q->next;//将*q结点从链中断开
free(q);//释放结点存储空间
return true;
}
//---------------查找----------------
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
if (i < 1)return NULL;
int j = 1;
LNode* p = L->next;//第1个结点指针赋给p
while (p != NULL && j < i)
{
p = p->next;
j++;
}
return p;
}
//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
LNode* p = L->next;
while (p != NULL && p->data != e)
{
p = p->next;
}
return p;
}
void List_print(LinkList& L)
{
LinkList t = L->next;
while (t->next != NULL)
{
printf("%d,", t->data);
t = t->next;
}
printf("%d\n", t->data);
}
void PutMenu()
{
printf("\n----------菜单----------\n");
printf("1.头插法创建单链表\n2 尾插法创建单链表\n");
printf("3.插入元素\n");
printf("4.删除元素\n");
printf("5.按序号查找结点\n");
printf("6.按值查找结点\n");
printf("请选择想执行的操作:\n");
}
int main()
{
LinkList L1;
InitList(L1);
//---------------菜单---------------
PutMenu();
int x;
while (~scanf_s("%d", &x))
{
if (x == 1)
{
//头插法创建单链表
List_HeadInsert(L1);
List_print(L1);
}
else if (x == 2)
{
//尾插法创建单链表
List_TailInsert(L1);
List_print(L1);
}
else if (x == 3)
{
int pos, e;
printf("请输入要插入的位置和元素:\n");
scanf_s("%d %d", &pos, &e);
ListInsert(L1, pos, e);
List_print(L1);
}
else if (x == 4)
{
int pos, e;
printf("请输入要删除的元素位置:\n");
scanf_s("%d", &pos);
ListDelete(L1, pos, e);
printf("被删元素:%d\n",e);
List_print(L1);
}
else if (x == 5)
{
LNode* p;
int n;
printf("请输入需要查找的序号:\n");
scanf_s("%d", &n);
p = GetElem(L1, n);
printf("查找结点的值:%d", p->data);
}
else if (x == 6)
{
LNode* p;
int n;
printf("请输入需要查找的结点值:\n");
scanf_s("%d", &n);
p =LocateElem(L1, n);
printf("success!");
}
PutMenu();
}
return 0;
}