无头单链表的各种操作

SList无头单链表

链表链表是一种物理结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

链表可分为以下3类:
1.单向、双向
2.带头、不带头
3.循环、非循环
组合起来就有8种链表结构。

但常用的基本就两种:
在这里插入图片描述

实现目标

利用无头单链表,并实现以下功能:
Slist

代码实现

//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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无头单链表是一种常见的链表数据结构,在 Java 中可以使用自定义的节点类来实现。以下是一个简单的无头单链表实现示例: ```java class Node { int data; Node next; public Node(int data) { this.data = data; this.next = null; } } class LinkedList { Node head; public LinkedList() { this.head = null; } // 在链表头部插入一个新节点 public void insertAtHead(int data) { Node newNode = new Node(data); newNode.next = head; head = newNode; } // 在链表尾部插入一个新节点 public void insertAtTail(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; return; } Node current = head; while (current.next != null) { current = current.next; } current.next = newNode; } // 打印链表元素 public void printList() { Node current = head; while (current != null) { System.out.print(current.data + " "); current = current.next; } System.out.println(); } } public class Main { public static void main(String[] args) { LinkedList list = new LinkedList(); list.insertAtHead(3); list.insertAtHead(2); list.insertAtHead(1); list.printList(); // 输出: 1 2 3 list.insertAtTail(4); list.insertAtTail(5); list.printList(); // 输出: 1 2 3 4 5 } } ``` 在上述示例中,`Node` 类表示链表节点,包含一个整型数据 `data` 和一个指向下一个节点的引用 `next`。`LinkedList` 类表示链表本身,包含一个指向链表头部的引用 `head`。链表操作包括在头部插入节点(`insertAtHead`)、在尾部插入节点(`insertAtTail`)和打印链表元素(`printList`)。在 `main` 方法中,我们创建一个链表实例并演示了插入节点和打印链表操作

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值