一、单链表定义
?单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。 ?根据第一个节点是否存放数据:分为带头节点(带哨兵位)的单链表与不带头节点(不带哨兵位)的单链表两种
二、不带头节点的单链表
2.1 单链表结构及接口定义
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}ListNode;
ListNode* CreateNode();
void SinListHeadInsert(ListNode **ppHead, ElemType elem);
void SinListHeadDelete(ListNode** ppHead);
void SinListTailInsert(ListNode** ppHead, ElemType elem);
void SinListTailDelete(ListNode** ppHead);
void SinListInsert(ListNode** ppHead, int pos, ElemType elem);
void SinListDelete(ListNode** ppHead, int pos);
void SinListPrint(ListNode* pHead);
int SinListFind(ListNode* pHead, ElemType value);
void Destory(ListNode** ppHead);
2.2 创建节点
ListNode* CreateNode(ElemType elem)
{
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newNode->data = elem;
newNode->next = NULL;
return newNode;
}
2.3 头插元素
void SinListHeadInsert(ListNode** ppHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
newNode->next = *ppHead;
*ppHead = newNode;
}
2.4 头删元素
void SinListHeadDelete(ListNode** ppHead)
{
if (*ppHead == NULL)
{
printf("单链表为空,头删失败\n");
}
else
{
ListNode* next = (*ppHead)->next;
free(*ppHead);
*ppHead = next;
}
}
2.5 尾插元素
void SinListTailInsert(ListNode** ppHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
if (*ppHead == NULL)
{
*ppHead = newNode;
}
else
{
ListNode* tail = *ppHead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newNode;
}
}
2.6 尾删元素
void SinListTailDelete(ListNode** ppHead)
{
if (*ppHead == NULL)
{
printf("单链表为空,尾删失败\n");
}
else
{
if ((*ppHead)->next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
ListNode* prev = NULL;
ListNode* tail = *ppHead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
prev->next = NULL;
}
}
}
2.7 指定位置插入元素
位序(位置)从1开始,即第一个节点位序为1
void SinListInsert(ListNode** ppHead, int pos, ElemType elem)
{
if (pos <= 0)
{
printf("位置不合法,插入失败\n");
}
else if (pos == 1)
{
ListNode* newNode = CreateNode(elem);
newNode->next = *ppHead;
*ppHead = newNode;
}
else
{
int i = 1;
ListNode* prev = NULL;
ListNode* cur = *ppHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (i == pos)
{
ListNode* newNode = CreateNode(elem);
newNode->next = cur;
prev->next = newNode;
}
else
{
printf("位置不合法,插入失败\n");
}
}
}
2.7 指定位置删除元素
void SinListDelete(ListNode** ppHead, int pos)
{
if (pos <= 0)
{
printf("位置不合法,删除失败\n");
}
else if (*ppHead == NULL)
{
printf("单链表为空,删除失败\n");
}
else if(pos == 1)
{
ListNode* next = (*ppHead)->next;
free(*ppHead);
*ppHead = next;
}
else
{
int i = 1;
ListNode* prev = NULL;
ListNode* cur = *ppHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (cur == NULL)
{
printf("位置不合法,删除失败\n");
}
else
{
prev->next = cur->next;
free(cur);
}
}
}
2.8 打印单链表
void SinListPrint(ListNode* pHead)
{
if (pHead == NULL)
{
printf("单链表为空\n");
}
else
{
ListNode* cur = pHead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
}
2.9 查找指定元素位置
查找指定值在单链表第一次出现位置,位置从1开始,未找到返回-1
int SinListFind(ListNode* pHead, ElemType value)
{
ListNode* cur = pHead;
int i = 1;
while (cur != NULL)
{
if (cur->data == value)
{
return i;
}
cur = cur->next;
i++;
}
return -1;
}
2.10 销毁单链表
void Destory(ListNode** ppHead)
{
ListNode* cur = *ppHead;
ListNode* next = NULL;
while (cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
*ppHead = NULL;
}
2.11 源代码
头文件SinList.h 内容:
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}ListNode;
ListNode* CreateNode();
void SinListHeadInsert(ListNode **ppHead, ElemType elem);
void SinListHeadDelete(ListNode** ppHead);
void SinListTailInsert(ListNode** ppHead, ElemType elem);
void SinListTailDelete(ListNode** ppHead);
void SinListInsert(ListNode** ppHead, int pos, ElemType elem);
void SinListDelete(ListNode** ppHead, int pos);
void SinListPrint(ListNode* pHead);
int SinListFind(ListNode* pHead, ElemType value);
void Destory(ListNode** ppHead);
源文件SinList.c 内容:
#include "SinList.h"
ListNode* CreateNode(ElemType elem)
{
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newNode->data = elem;
newNode->next = NULL;
return newNode;
}
void SinListHeadInsert(ListNode** ppHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
newNode->next = *ppHead;
*ppHead = newNode;
}
void SinListHeadDelete(ListNode** ppHead)
{
if (*ppHead == NULL)
{
printf("单链表为空,头删失败\n");
}
else
{
ListNode* next = (*ppHead)->next;
free(*ppHead);
*ppHead = next;
}
}
void SinListTailInsert(ListNode** ppHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
if (*ppHead == NULL)
{
*ppHead = newNode;
}
else
{
ListNode* tail = *ppHead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newNode;
}
}
void SinListTailDelete(ListNode** ppHead)
{
if (*ppHead == NULL)
{
printf("单链表为空,尾删失败\n");
}
else
{
if ((*ppHead)->next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
ListNode* prev = NULL;
ListNode* tail = *ppHead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
prev->next = NULL;
}
}
}
void SinListInsert(ListNode** ppHead, int pos, ElemType elem)
{
if (pos <= 0)
{
printf("位置不合法,插入失败\n");
}
else if (pos == 1)
{
ListNode* newNode = CreateNode(elem);
newNode->next = *ppHead;
*ppHead = newNode;
}
else
{
int i = 1;
ListNode* prev = NULL;
ListNode* cur = *ppHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (i == pos)
{
ListNode* newNode = CreateNode(elem);
newNode->next = cur;
prev->next = newNode;
}
else
{
printf("位置不合法,插入失败\n");
}
}
}
void SinListDelete(ListNode** ppHead, int pos)
{
if (pos <= 0)
{
printf("位置不合法,删除失败\n");
}
else if (*ppHead == NULL)
{
printf("单链表为空,删除失败\n");
}
else if(pos == 1)
{
ListNode* next = (*ppHead)->next;
free(*ppHead);
*ppHead = next;
}
else
{
int i = 1;
ListNode* prev = NULL;
ListNode* cur = *ppHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (cur == NULL)
{
printf("位置不合法,删除失败\n");
}
else
{
prev->next = cur->next;
free(cur);
}
}
}
void SinListPrint(ListNode* pHead)
{
if (pHead == NULL)
{
printf("单链表为空\n");
}
else
{
ListNode* cur = pHead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
}
int SinListFind(ListNode* pHead, ElemType value)
{
ListNode* cur = pHead;
int i = 1;
while (cur != NULL)
{
if (cur->data == value)
{
return i;
}
cur = cur->next;
i++;
}
return -1;
}
void Destory(ListNode** ppHead)
{
ListNode* cur = *ppHead;
ListNode* next = NULL;
while (cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
*ppHead = NULL;
}
源文件main.c 内容:
#include "SinList.h"
void menu()
{
printf("------------------------------\n");
printf("-- H. 头插元素 h. 头删元素 --\n");
printf("-- T. 尾插元素 t. 尾删元素 --\n");
printf("-- I. 插入元素 D. 删除元素 --\n");
printf("-- F. 查找元素 P. 打印元素 --\n");
printf("--------- Q. 退出 --------\n");
printf("------------------------------\n\n");
}
int main()
{
ListNode* pHead = NULL;
char choose = 'Q';
do
{
menu();
printf("请选择:");
choose = getchar();
ElemType elem;
int position = -1;
getchar();
switch (choose)
{
case 'H':
printf("请输入待插入元素值:");
scanf("%d", &elem);
SinListHeadInsert(&pHead, elem);
getchar();
break;
case 'h':
SinListHeadDelete(&pHead);
break;
case 'T':
printf("请输入待插入元素值:");
scanf("%d", &elem);
SinListTailInsert(&pHead,elem);
getchar();
break;
case 't':
SinListTailDelete(&pHead);
break;
case 'I':
printf("请输入待插入元素位序及值,例:2 5 >");
scanf("%d %d", &position, &elem);
SinListInsert(&pHead, position, elem);
getchar();
break;
case 'D':
printf("请输入待删除元素位序:");
scanf("%d", &position);
SinListDelete(&pHead, position);
getchar();
break;
case 'F':
printf("请输入待查找元素的值:");
scanf("%d", &elem);
position = SinListFind(pHead, elem);
getchar();
if (position == -1)
{
printf("元素:%d 不在单链表中\n", elem);
}
else
{
printf("元素:%d 的位序为:%d\n", elem, position);
}
break;
case 'P':
SinListPrint(pHead);
break;
case 'Q':
Destory(&pHead);
printf("退出成功\n");
break;
default:
printf("选择错误,请重新选择!!!\n");
break;
}
} while (choose != 'Q');
return 0;
}
三、带头节点的单链表
3.1 单链表结构及接口定义
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}ListNode;
ListNode* CreateNode();
void SinListHeadInsert(ListNode *pHead, ElemType elem);
void SinListHeadDelete(ListNode *pHead);
void SinListTailInsert(ListNode *pHead, ElemType elem);
void SinListTailDelete(ListNode *pHead);
void SinListInsert(ListNode *pHead, int pos, ElemType elem);
void SinListDelete(ListNode *pHead, int pos);
void SinListPrint(ListNode *pHead);
int SinListFind(ListNode *pHead, ElemType value);
ListNode* Destory(ListNode* pHead);
3.2 创建节点
ListNode* CreateNode(ElemType elem)
{
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newNode->data = elem;
newNode->next = NULL;
return newNode;
}
3.3 头插元素
void SinListHeadInsert(ListNode* pHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
newNode->next = pHead->next;
pHead->next = newNode;
}
3.3 头删元素
void SinListHeadDelete(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空,头删失败\n");
}
else
{
ListNode* Node = pHead->next;
pHead->next = pHead->next->next;
free(Node);
}
}
3.4 尾插元素
void SinListTailInsert(ListNode* pHead, ElemType elem)
{
ListNode* tail = pHead;
while (tail->next != NULL)
{
tail = tail->next;
}
ListNode* newNode = CreateNode(elem);
tail->next = newNode;
}
3.5 尾删元素
void SinListTailDelete(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空,尾删失败\n");
}
else
{
ListNode* prev = NULL;
ListNode* tail = pHead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
prev->next = NULL;
}
}
3.6 指定位置插入元素
void SinListInsert(ListNode* pHead, int pos, ElemType elem)
{
if (pos <= 0)
{
printf("位置不合法,插入失败\n");
}
else
{
int i = 0;
ListNode* prev = NULL;
ListNode* cur = pHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (i == pos)
{
ListNode* newNode = CreateNode(elem);
newNode->next = cur;
prev->next = newNode;
}
else
{
printf("位置不合法,插入失败\n");
}
}
}
3.7 指定位置删除元素
void SinListDelete(ListNode* pHead, int pos)
{
if (pos <= 0)
{
printf("位置不合法,删除失败\n");
}
else if(pHead->next == NULL)
{
printf("单链表为空,删除失败\n");
}
else
{
int i = 0;
ListNode* prev = NULL;
ListNode* cur = pHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (cur == NULL)
{
printf("位置不合法,删除失败\n");
}
else
{
prev->next = cur->next;
free(cur);
}
}
}
3.8 打印单链表
void SinListPrint(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空\n");
}
else
{
ListNode* cur = pHead->next;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
}
3.9 查找指定元素位置
int SinListFind(ListNode* pHead, ElemType value)
{
ListNode* cur = pHead->next;
int i = 1;
while (cur != NULL)
{
if (cur->data == value)
{
return i;
}
cur = cur->next;
i++;
}
return -1;
}
3.10 销毁单链表
ListNode* Destory(ListNode* pHead)
{
ListNode* cur = pHead;
ListNode* next = NULL;
while (cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
return NULL;
}
3.11 源代码
头文件SinList.h 内容:
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}ListNode;
ListNode* CreateNode();
void SinListHeadInsert(ListNode *pHead, ElemType elem);
void SinListHeadDelete(ListNode *pHead);
void SinListTailInsert(ListNode *pHead, ElemType elem);
void SinListTailDelete(ListNode *pHead);
void SinListInsert(ListNode *pHead, int pos, ElemType elem);
void SinListDelete(ListNode *pHead, int pos);
void SinListPrint(ListNode *pHead);
int SinListFind(ListNode *pHead, ElemType value);
ListNode* Destory(ListNode* pHead);
源文件SinList.c 内容:
#include "SinList.h"
ListNode* CreateNode(ElemType elem)
{
ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
if (newNode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newNode->data = elem;
newNode->next = NULL;
return newNode;
}
void SinListHeadInsert(ListNode* pHead, ElemType elem)
{
ListNode* newNode = CreateNode(elem);
newNode->next = pHead->next;
pHead->next = newNode;
}
void SinListHeadDelete(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空,头删失败\n");
}
else
{
ListNode* Node = pHead->next;
pHead->next = pHead->next->next;
free(Node);
}
}
void SinListTailInsert(ListNode* pHead, ElemType elem)
{
ListNode* tail = pHead;
while (tail->next != NULL)
{
tail = tail->next;
}
ListNode* newNode = CreateNode(elem);
tail->next = newNode;
}
void SinListTailDelete(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空,尾删失败\n");
}
else
{
ListNode* prev = NULL;
ListNode* tail = pHead;
while (tail->next != NULL)
{
prev = tail;
tail = tail->next;
}
free(tail);
prev->next = NULL;
}
}
void SinListInsert(ListNode* pHead, int pos, ElemType elem)
{
if (pos <= 0)
{
printf("位置不合法,插入失败\n");
}
else
{
int i = 0;
ListNode* prev = NULL;
ListNode* cur = pHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (i == pos)
{
ListNode* newNode = CreateNode(elem);
newNode->next = cur;
prev->next = newNode;
}
else
{
printf("位置不合法,插入失败\n");
}
}
}
void SinListDelete(ListNode* pHead, int pos)
{
if (pos <= 0)
{
printf("位置不合法,删除失败\n");
}
else if(pHead->next == NULL)
{
printf("单链表为空,删除失败\n");
}
else
{
int i = 0;
ListNode* prev = NULL;
ListNode* cur = pHead;
while (cur != NULL && i < pos)
{
prev = cur;
cur = cur->next;
i++;
}
if (cur == NULL)
{
printf("位置不合法,删除失败\n");
}
else
{
prev->next = cur->next;
free(cur);
}
}
}
void SinListPrint(ListNode* pHead)
{
if (pHead->next == NULL)
{
printf("单链表为空\n");
}
else
{
ListNode* cur = pHead->next;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
}
int SinListFind(ListNode* pHead, ElemType value)
{
ListNode* cur = pHead->next;
int i = 1;
while (cur != NULL)
{
if (cur->data == value)
{
return i;
}
cur = cur->next;
i++;
}
return -1;
}
ListNode* Destory(ListNode* pHead)
{
ListNode* cur = pHead;
ListNode* next = NULL;
while (cur != NULL)
{
next = cur->next;
free(cur);
cur = next;
}
return NULL;
}
源文件main.c 内容:
#include "SinList.h"
void menu()
{
printf("------------------------------\n");
printf("-- H. 头插元素 h. 头删元素 --\n");
printf("-- T. 尾插元素 t. 尾删元素 --\n");
printf("-- I. 插入元素 D. 删除元素 --\n");
printf("-- F. 查找元素 P. 打印元素 --\n");
printf("--------- Q. 退出 --------\n");
printf("------------------------------\n\n");
}
int main()
{
ListNode* pHead = (ListNode*)malloc(sizeof(ListNode));
pHead->next = NULL;
char choose = 'Q';
do
{
menu();
printf("请选择:");
choose = getchar();
ElemType elem;
int position = -1;
getchar();
switch (choose)
{
case 'H':
printf("请输入待插入元素值:");
scanf("%d", &elem);
SinListHeadInsert(pHead, elem);
getchar();
break;
case 'h':
SinListHeadDelete(pHead);
break;
case 'T':
printf("请输入待插入元素值:");
scanf("%d", &elem);
SinListTailInsert(pHead,elem);
getchar();
break;
case 't':
SinListTailDelete(pHead);
break;
case 'I':
printf("请输入待插入元素位序及值,例:2 5 >");
scanf("%d %d", &position, &elem);
SinListInsert(pHead, position, elem);
getchar();
break;
case 'D':
printf("请输入待删除元素位序:");
scanf("%d", &position);
SinListDelete(pHead, position);
getchar();
break;
case 'F':
printf("请输入待查找元素的值:");
scanf("%d", &elem);
position = SinListFind(pHead, elem);
getchar();
if (position == -1)
{
printf("元素:%d 不在单链表中\n", elem);
}
else
{
printf("元素:%d 的位序为:%d\n", elem, position);
}
break;
case 'P':
SinListPrint(pHead);
break;
case 'Q':
pHead = Destory(pHead);
printf("退出成功\n");
break;
default:
printf("选择错误,请重新选择!!!\n");
break;
}
} while (choose != 'Q');
return 0;
}
|