SList无头单链表
链表是一种物理结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表可分为以下3类:
1.单向、双向
2.带头、不带头
3.循环、非循环
组合起来就有8种链表结构。
但常用的基本就两种:
实现目标
利用无头单链表,并实现以下功能:
代码实现
//Sysutil.h
#ifndef __SYSUTIL_H___
#define __SYSUTIL_H___
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#pragma warning(disable:4996)
#endif
//SList.h
#pragma once
#include "Sysutil.h"
#define ElemType int
//无头单链表
typedef struct SListNode
{
ElemType data;//数据域
struct SListNode* next;//指针域
}SListNode;
typedef struct SList
{
SListNode* head;
}SList;
void SListMenu();
void SListInit(SList* plist);
static SListNode* BuyNode();
void SListPushBack(SList* plist, ElemType x);
void SListShow(SList* plist);
void SListPushFront(SList* plist, ElemType x);
int SListLength(SList* plist);
void SListPopBack(SList* plist);
void SListPopFront(SList* plist);
SListNode* SListFind(SList* plist, ElemType key);
void SListClear(SList* plist);
void SListDeleteByVal(SList* plist, ElemType x);
void SListPushByVal(SList* plist, ElemType key);
void SListReverse(SList* plist);
void SListPopAllSame(SList* plist, ElemType key);
void SListPushPos(SList* plist, int pos, ElemType x);
void SListPopPos(SList* plist, int pos);
void SListDestroy(SList* plist);
/
void SListMenu()
{
printf("*******************************************\n");
printf("***** [1]显示长度 [2]头部插入 *****\n");
printf("***** [3]尾部插入 [4]按值插入 *****\n");
printf("***** [5]打印所有 [6]头部删除 *****\n");
printf("***** [7]尾部删除 [8]按值删除 *****\n");
printf("***** [9]按值查找 [10]销毁链表 *****\n");
printf("***** [11]元素翻转 [12]同值删除 *****\n");
printf("***** [13]按位插入 [14]按位删除 *****\n");
printf("***** [15]清除内容 [0]退出 *****\n");
printf("*******************************************\n");
}
void SListInit(SList* plist)
{//初始化:无头单链表
plist->head = NULL;
}
static SListNode* BuyNode()
{
SListNode* p = (SListNode*)malloc(sizeof(SListNode));//申请节点
assert(p != NULL);
p->data = 0;//节点初始化
p->next = NULL;
return p;
}
void SListPushBack(SList* plist, ElemType x)
{
assert(plist);//合法检查
SListNode* p = plist->head;
SListNode* s = BuyNode(); //创建新节点,存储数据
s->data = x;
if (NULL == p) {//空表,链接
plist->head = s;
}
else {//非空,尾插
while (NULL != p->next) {//找到表尾
p = p->next;
}
p->next = s;//链接
}
}
void SListShow(SList* plist)
{
assert(plist);
SListNode* p = plist->head;//继承head
while (NULL != p) {//打印
printf("%d-->",p->data);
p = p->next;
}
printf("end\n");//结束指示
}
void SListPushFront(SList* plist, ElemType x)
{
assert(plist);//合法检查
SListNode* s = BuyNode(); //创建新节点,存储数据
s->data = x;
s->next = plist->head;//继承 head->next
plist->head = s;//链接
}
int SListLength(SList* plist)
{
assert(plist);
int cnt = 0;
SListNode* p = plist->head;
while (NULL != p) {//遍历求长度
p = p->next;
cnt++;
}
return cnt;
}
void SListPopBack(SList* plist)
{
assert(plist);
SListNode* p = plist->head;
if (NULL != p) {
if (p->next == NULL) {//只有一个节点
plist->head = NULL;
}
else {//多个节点
SListNode* pre = BuyNode();
while (p->next != NULL) {//寻找最后一个节点
pre = p;//前一个节点
p = p->next;
}
pre->next = NULL;
}
free(p);
}
else {
printf("空SList!\n");
}
}
void SListPopFront(SList* plist)
{
assert(plist);
SListNode* p = plist->head;
if (NULL != p) {
plist->head = p->next;//指向下一节点
free(p);
}
}
SListNode* SListFind(SList* plist, ElemType key)
{
assert(plist);
SListNode* p = plist->head;
//非空表,遍历寻找
while (NULL != p && p->data != key)
{
p = p->next;
}
return p;
}
void SListClear(SList* plist)
{
assert(plist);
SListNode* p = plist->head;
while (NULL != p){
plist->head = p->next;
free(p);
p = plist->head; //指向下个节点
}
}
void SlistDestroy(SList* plist)
{
assert(plist);
SListClear(plist);
}
void SListDeleteByVal(SList* plist, ElemType x)
{
assert(plist);
SListNode* p = plist->head;
SListNode* pre = NULL;
while (p != NULL && p->data != x) {
pre = p;
p = p->next;
}
if (p != NULL) {
if (pre == NULL)//第一个节点
plist->head = p->next;
else//中间节点
pre->next = p->next;
free(p);
}
}
void SListPushByVal(SList* plist, ElemType key)
{
assert(plist);
SListNode* p = BuyNode();
p->data = key;
if (NULL == plist->head)
plist->head = p;
else {
SListNode* s = plist->head;
SListNode* pre = NULL;
while (s != NULL && key > s->data) {
pre = s;
s = s->next;
}
if (NULL == pre) {
p->next = s;
plist->head = p;
}
else {
p->next = pre->next;
pre->next = p;
}
}
}
void SListReverse(SList* plist)
{
assert(plist);
if (NULL == plist->head->next || NULL == plist->head)//不需要转置
return;
SListNode* p = plist->head->next;//继承当前SList的第二个节点
plist->head->next = NULL;//断开与第二个节点的链接
SListNode* q = p; //
while (NULL != q) {//头插
q = q->next;
p->next = plist->head;
plist->head = p;
p = q;
}
}
void SListPopAllSame(SList* plist, ElemType key)
{
assert(plist);
SListNode* p = plist->head;
SListNode* pre = NULL;
while (p != NULL) {
while (p != NULL && p->data != key) {
pre = p;
p = p->next;
}
if (p != NULL) {
if (pre == NULL)//第一个节点
plist->head = p->next;
else//中间节点
pre->next = p->next;
free(p);//释放data=key的节点
}
if (NULL != pre)//
p = pre->next;
else
p = plist->head;//从头开始
}
}
void SListPushPos(SList* plist, int pos, ElemType x)
{
assert(plist);
int len = SListLength(plist);
if (pos<1 || pos>len) {
printf("插入位置非法!\n");
return;
}
SListNode* s = BuyNode();
s->data = x;
int cnt = 1;
SListNode* p = plist->head;
while (cnt != pos) {
p = p->next;
cnt++;
}
s->next = p->next;
p->next = s;
}
void SListPopPos(SList* plist, int pos)
{
assert(plist);
int len = SListLength(plist);
if (pos<1 || pos>len) {
printf("输入位置非法!\n");
return;
}
int cnt = 1;
SListNode* p = plist->head;
SListNode* pre = NULL;
while (p != NULL && cnt != pos) {
pre = p;
p = p->next;
cnt++;
}
if (p != NULL) {
if (pre == NULL)//第一个节点
plist->head = p->next;
else//中间节点
pre->next = p->next;
free(p);
}
}
void SListDestroy(SList* plist)
{
assert(plist);
SListClear(plist);
}
#include "SlistNode.h"
int main()
{
SList mylist;
SListInit(&mylist);
int choice;
int quit = 0;
int pos = 0;
ElemType item;
while (!quit) {
SListMenu();
printf("请输入你的选择#");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Slist长度为[%d]\n", SListLength(&mylist));
break;
case 2:
printf("请输入想要插入的数据(-1结束)#");
while (scanf("%d", &item), item != -1) {
SListPushFront(&mylist, item);
}
SListShow(&mylist); break;
case 3:
printf("请输入想要插入的数据(-1结束)#");
while (scanf("%d", &item), item != -1) {
SListPushBack(&mylist, item);
}
SListShow(&mylist);
break;
case 4:
printf("请输入想要插入的数据#");
scanf("%d", &item);
SListPushByVal(&mylist, item);
SListShow(&mylist);
break; SListShow(&mylist);break;
case 5:SListShow(&mylist); break;
case 6:SListPopFront(&mylist); SListShow(&mylist); break;
case 7:SListPopBack(&mylist); SListShow(&mylist); break;
case 8:
printf("请输入想要删除的数据#");
scanf("%d", &item);
SListDeleteByVal(&mylist, item);
SListShow(&mylist);
break;
case 9:
printf("请输入想要查找的数据)#");
scanf("%d", &item);
SListNode* p = SListFind(&mylist, item);
if (NULL != p) {
printf("[%d]的物理存储地址为[%p]\n", item, &p);
}
else
printf("[%d]不存在于SList中!\n", item);
break;
case 10:SlistDestroy(&mylist); break;
case 11:SListReverse(&mylist); SListShow(&mylist); break;
case 12:
printf("请输入想要全部删除的同一数据)#");
scanf("%d", &item);
SListPopAllSame(&mylist, item);
break;
case 13:
if (SListLength(&mylist) == 0) {
printf("空表!请使用其他选项加入数据!\n");
break;
}
printf("请输入想要插入的位置及数据(1-%d)#",SListLength(&mylist));
scanf("%d %d", &pos, &item);
SListPushPos(&mylist, pos,item);
SListShow(&mylist);
break;
case 14:
if (SListLength(&mylist) == 0) {
printf("空表!\n");
break;
}
printf("请输入想要删除的位置(1-%d)#", SListLength(&mylist));
scanf("%d", &pos);
SListPopPos(&mylist, pos);
break;
case 15:SListClear(&mylist); break;
case 0:printf("再见!\n");SlistDestroy(&mylist); quit = 1; break;
default:printf("输入错误!请重新输入#"); break;
}
system("pause");
system("cls");
}
return 0;
}