单链表的增删查 逆置 倒数第k个节点等问题

    对于单链表而言,它没有双链表那么复杂,它只有头节点,尾节点,节点数据,后继指针。在下面本人实现了 单链表的 增   删   插  查  改。
    
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>
typedef int Datatype;
typedef struct SListNode
{
	Datatype data;
	struct SListNode*next;
}SListNode;
void PushBack(SListNode*&pHead, Datatype x);
void PopBack(SListNode *&pHead);
void PrintSlist(SListNode *&PHead);
void PushFrot(SListNode*&pHead,Datatype x);
void PopFront(SListNode*&pHead);
SListNode *Find(SListNode*pHead, Datatype x);
//void Insert(SListNode*pHead, Datatype pos, Datatype x);
void Insert(SListNode*pHead,  Datatype x);
void Erase(SListNode*&pHead,SListNode *pos );
void InsertNoNode(SListNode *pos, Datatype x);

SListNode* _BuyNode(Datatype x)
{
	SListNode *temp = (SListNode*)malloc(sizeof(SListNode));
	temp->data = x;
	temp->next = NULL;
	return temp;
}
void PushBack(SListNode*&pHead, Datatype x)
{
	//1 空   2  不为空
	if (pHead == NULL)
	{
		pHead = _BuyNode(x);
	}
	else
	{
		SListNode *tail = pHead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = _BuyNode(x);
	}
}
void PopBack(SListNode *&pHead)
{
	//1空  2 一个节点  3 多个节点  
	if(pHead == NULL)
	{
		return;
	}
	else if (pHead->next == NULL)
	{
		free(pHead);
		pHead = NULL;
	}
	else{
		SListNode *tail = pHead;
		SListNode *tem = NULL;
		while (tail->next != NULL)
		{
			tem = tail;
			tail = tail->next;
		}
		free(tail);
		tem->next = NULL; 
	}
}
void PrintSlist(SListNode *&PHead)  //打印链表
{
	SListNode*cur = PHead;
	while (cur!=NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
void PushFrot(SListNode*&pHead, Datatype x)   //头插
{
	if (pHead == NULL)
	{
		pHead = _BuyNode(x);
	}
	else
	{
		SListNode *tmp = _BuyNode(x);
		tmp->next = pHead;
		pHead = tmp;
	}
}
void PopFront(SListNode*&pHead)    //单链表头删
{
	//1 空
	//2 一个结点
	//3 一个以上的节点
	if (pHead == NULL)
	{
		return;
	}
	else if(pHead->next == NULL)
	{
		free(pHead);
		pHead = NULL;
	}
	else
	{
		SListNode *tmp = pHead;
		pHead = pHead->next;
		free(tmp);
	}

}

SListNode *Find(SListNode*pHead, Datatype x)    //查找节点
{
	//assert(pHead);
	SListNode *tail = NULL;//当前指针
	Datatype tmp ;   //保存节点数据
    if (pHead->data == x)
	{
		return pHead;
	}
	else
	{
		tail=pHead->next;
		while (tail!= NULL)
		{
			tmp = tail->data;
			if (tmp == x)  //把节点数据与要查找的数比较
			{
				return tail; //返回所要查找结点的地址
			}
			else
			{
				tail =tail->next;
			}
		}
		printf("没有查到该数据!\n");
	}
}

void Insert(SListNode*pos, Datatype x)  ////在指定节点  插入数据
{
	assert(pos);
	SListNode *tmp = _BuyNode(x);
	tmp->next = pos->next;
	pos->next = tmp;
}

void Erase(SListNode *&pHead,SListNode *pos) //删除指定位置的节点
{
	assert(pos);
	assert(pHead);
	if (pHead == pos)
	{
		pHead = pHead->next;
		free(pos);
		return;
	}
	SListNode *prv = pHead;
	while (prv)
	{
		if (prv->next == pos)
		{
			prv->next = pos->next;
			free(pos);
			break;
		}
		prv = prv->next;
	}

}

//删除一个无头单链表
void DelNoNode(SListNode *pos)
{
	assert(pos);
	assert(pos->next);
	SListNode *del = pos->next;
	SListNode *next = del->next;
	pos->data = del->data;
	pos->next = next;
	free(del);
}
//在无头单链表的一个非头节点前插入一个节点
void InsertNoNode(SListNode *pos, Datatype x)
{
	assert(pos);
	//assert(pos->next);
//1 种方法	//Datatype temp = 0;
	//SListNode *behind = pos;
	//SListNode*prv =_BuyNode(x);
	//SListNode *next = behind->next;
	//pos->next = prv;
	//prv->next = next;
	//temp = pos->data;
	//pos->data = prv->data;
	//prv->data = temp;
//2 种方法
	SListNode*prv = _BuyNode(pos->data);
	prv->next = pos->next;
	pos->next = prv;
	pos->data = x;
}
//查找中间节点
SListNode *FindmidNode(SListNode *phead)
{
	SListNode *fast = phead;
	SListNode *slow = phead;
	while (fast&&fast->next)
	{
		fast = fast->next->next;
        slow = slow->next;
	}
	return slow;
}

    //找倒数第k个节点
SListNode *FindkNode(SListNode *phead, int k)
{
	SListNode *fast = phead;
	SListNode *slow = phead;
    /*for (int i = 1; i<=k-1; i++)
		{
		 	fast = fast->next;
		}
	while (fast->next)
	{

		slow = slow->next;
		fast = fast->next;
	}*/
	while (fast&&k--)
	{

		fast= fast->next;
		if (fast == NULL)
			return NULL;
	}
	while (fast)
	{
		slow = slow->next;
		fast = fast->next;
	}
	return slow;
}
//从尾到头打印链表
void PrintTailToHead(SListNode*phead)
{
	if (phead)
	{
		PrintTailToHead(phead->next);
		printf("%d ", phead->data);
	}
}
//
SListNode *Reverse(SListNode *phead)//单链表的逆置
{
	SListNode *cur = phead;
	SListNode *newhead = NULL;
	while (cur)
	{
		SListNode*tmp =cur;
		cur = cur->next;
		tmp->next =newhead;
		newhead = tmp;
	}
	return newhead;
}
void test1()
{
	SListNode*list = NULL;
	PushBack(list, 1);
	PushBack(list, 3);
	PushBack(list, 2);
	PushBack(list, 4);
	PushBack(list, 6);
	PrintSlist(list);
}
void test2()
{
	SListNode*list = NULL;
	PushBack(list, 1);
	PushBack(list, 2);
	PushBack(list, 3);
	PushBack(list, 4);
	PushBack(list, 5);
	PushBack(list, 6);
	PushBack(list, 7);
	PrintSlist(list);
	//Find(list, 4);
	//Insert(list,7, 8);
	SListNode *pos = Find(list, 1);
	Erase(list,pos );
	PrintSlist(list);
}
void test3()
{
	SListNode*list = NULL;
	PushBack(list, 1);
	PushBack(list, 2);
	PushBack(list, 3);
	PushBack(list, 4);
	PushBack(list, 5);
	PushBack(list, 6);
	PushBack(list, 7);
	PrintSlist(list);
	SListNode *pos = Find(list ,7);
	Insert(pos, 2);
	PrintSlist(list);
}
void test4()
{
	SListNode*list = NULL;
	PushBack(list, 1);
	PushBack(list, 2);
	PushBack(list, 3);
	PushBack(list, 4);
	PushBack(list, 5);
	PushBack(list, 6);
	PushBack(list, 7);
	PrintSlist(list);
	/*SListNode *pos = list;
	DelNoNode(pos);*/
	SListNode *pos = Find(list,1);
	InsertNoNode(pos, 9);
	PrintSlist(list);
}
void test5()
{
	SListNode *list = NULL;
	PushBack(list, 1);
	PushBack(list, 8);
	PushBack(list, 2);
	PushBack(list, 3);
	PushBack(list, 4);
	PushBack(list, 5);
	PrintSlist(list);
	//SListNode*pos = FindmidNode(list);
	SListNode*pos =FindkNode(list, 5);
	printf("%d\n", pos->data);
	//PrintSlist(list);
}
void test6()
{
	SListNode*list = NULL;
	PushBack(list, 1);
	PushBack(list, 3);
	PushBack(list, 2);
	PushBack(list, 4);
	PushBack(list, 6);
	// 
	SListNode*pos=Reverse(list);
	PrintTailToHead(pos);
}
int main()
{
	//test1();
	test6();
	system("pause");
	return 0;
}

以上如果发现有错的地方或者还有其他建议,希望提出宝贵意见。谢谢!!!

时间: 2024-10-20 16:08:32

单链表的增删查 逆置 倒数第k个节点等问题的相关文章

Leetcode:Reverse Linked List II 单链表区间范围内逆置

Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ le

单链表的增删查改等基本操作C++实现

单链表的初始化.增删查改.遍历一次找中间结点.删除一个无头单链表的非尾结点(不给头结点) #include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef int DataType; typedef struct ListNode { struct ListNode* _next; DataType _data; }ListNode; void InitList(ListNode* &pHead) {

Java带头节点单链表的增删融合以及是否有环

带头节点单链表 1.优势: 1)当链表为空时,指针指向头结点,不会发生null指针异常 2)方便特殊操作(删除第一个有效节点或者插入一个节点在表头) 3)单链表加上头结点之后,无论单链表是否为空,头指针始终指向头结点,因此空表和非空表的处理也统一了,方便了单链表的操作,也减少了程序的复杂性和出现bug的机会. 4)代码更加简单易懂 2.相关操作 1)建立单链表 即建立一个头结点 static class Entry<T> { T data; // 链表节点的数据域 Entry<T>

C语言实现单链表的遍历,逆序,插入,删除

单链表的遍历,逆序,插入,删除 #include<stdio.h> #include<stdlib.h> #include <string.h> #define bzero(a, b) memset(a, 0, b)//windows平台下无bzero函数. 增加宏拓展移植性 struct node { int data; //有效数据 struct node *pNext;//指向下一个节点的指针 }; struct node * make_node(int data

算法总结之 在单链表和双链表中删除倒数第k个节点

分别实现两个函数,一个可以删除单链表中倒数第k个节点,另一个可以删除双链表中倒数第k个节点 思路: 如果链表为空,或者k<1 参数无效 除此之外 让链表从头开始走到尾,每移动一步,就让k的值减1 当链表走到头时候 如果k值大于0   说明不用调整  因为链表根本没有倒数第k个节点 此时将原链表直接返回即可 如果k值=0,说明链表倒数第k个节点就是头节点,此时直接返回head.next 也就是原链表的第二个节点 让第二个节点作为链表的头节点,此时直接返回head.next 如果k值<0  重新从

2.2 在单链表和双链表中删除倒数第K个节点

题目:分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点 要求:如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1) My: 删除单链表或双链表中倒数第K个节点,核心代码(单链表和双链表的方法定义参见另一篇文:https://www.cnblogs.com/latup/p/9823179.html): 1 def del_k(L, k): 2 index = L.length - k + 1 3 L.delt(index) 原文地址:htt

删除单链表中倒数第 k 个节点

思路 1 :两个指针 p1 ,p2 ,p1从头开始遍历,当 p1 到达第 k 个节点时,p2 开始: 当 P1 到达链表的最后一个节点时,p2 所指的节点则为链表中倒数第 k 个节点. public class Node{ public int data; public Node next; public Node(int data){ this.data = data; } public Node removeLastKNode(Node head,int k){ if(head == nul

【剑指offer】链表倒数第k个节点

转载请注明出处:http://blog.csdn.net/ns_code/article/details/25662121 在Cracking the Code Interview上做过了一次,这次在九度OJ上测试,AC. 题目描述: 输入一个链表,输出该链表中倒数第k个结点.(hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为两个整数n和k(0<=n<=1000, 0<=k<=1000):n代表将要输入的链表元素的

求链表的倒数第k个节点

问题描述:给定一个链表的头节点,求出链表的倒数第k个节点. 分析:这是链表里的经典问题,存在多种解法,下面给大家分享下我的想法. 解法一:很直观的一种做法是从头到尾扫描链表,然后求倒数第k个,但是由于单链表无法从尾部向头部扫描, 因此可以借助其他的辅助空间去存储扫描过的所有节点,例如,数组或栈均可. 解法二:计算出链表中节点的总数为n,根据k 将其转化为正数的第n-k+1个节点,然后在从链表头开始走n-k+1个节点,就是所求. 解法三:可以设置两个指针实现,假设两个指针分别为p1和p2,p1从链