反向打印单链表的结果

一、设计思路

一种方式就是将单链表进行反转,然后打印出来,但是这种方式会破坏其结构!如果突然要求正向打印,那么就很麻烦,还要再反转回去;另外一种方式就是使用栈的方式实现。

二、代码

package linkedList;

import java.util.Stack;

/*
 * 题目要求:
	使用带head头的单向链表实现 –水浒英雄排行榜管理
	完成对英雄人物的增删改查操作, 注: 删除和修改,查找可以考虑学员独立完成,也可带学员完成
	第一种方法在添加英雄时,直接添加到链表的尾部
	第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
	
	各大厂关于链表的面试题:
	1.查找求单链表中有效节点的个数
	2.单链表中的倒数第k个结点 【新浪面试题】
	3.单链表的反转【腾讯面试题,有点难度】
	4.从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】
	5.合并两个有序的单链表,合并之后的链表依然有序【课后练习.】

*/



/*
	1.对链表进行相关操作
*/
public class SingleLinkedListDemo {
	public static void main(String[] args) {
		// 初始化数据
		HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
		HeroNode hero2 = new HeroNode(2, "李逵", "黑旋风");
		HeroNode hero3 = new HeroNode(4, "花和尚", "鲁智深");
		HeroNode hero4 = new HeroNode(3, "孙二娘", "母夜叉");
		
		SingleLinkedList linkedList = new SingleLinkedList();
		
		/*****************0.链表基本的增删改查操作**********************/
		
		// 增(无序)
		System.out.printf("链表:\n");
		linkedList.addToEnd(hero1);
		linkedList.addToEnd(hero2);
		linkedList.addToEnd(hero3);
		linkedList.addToEnd(hero4);
		
		// 增(有序)
//		linkedList.addWithOrder(hero1);
//		linkedList.addWithOrder(hero4);
//		linkedList.addWithOrder(hero3);
//		linkedList.addWithOrder(hero2);
		
		// 删(输入序号删除节点)
//		linkedList.delNode(2);
		
		// 改
//		linkedList.reviseNode(3, "李逵", "黑旋风");
		
		// 查
		linkedList.showLinkedList(); //显示链表信息
		/**************************end*********************************/
		
		
		/*****************1.各大厂的链表模块的面试题********************/

		// 面试题:返回有效节点个数
//		System.out.println(linkedList.getHeader());
//		int validLength = getLength(linkedList.getHeader());
//		System.out.printf("%s%d","有效链表长度为:", validLength);
		
		// 新浪:返回倒数第k个节点
//		int lastIndex = 3; //倒数第二个节点
//		if(0<lastIndex && lastIndex<=validLength) {
//			int paramIndex = validLength - lastIndex + 1;
//			HeroNode reverseNode = getReverseNode(linkedList.getHeader(), paramIndex);
//			System.out.printf("%s%d%s","\n\n倒数第",lastIndex,"个节点为:");
//			System.out.println("no."+ reverseNode.number + "---" + reverseNode.name + "---" + reverseNode.nickName);
//		}
		
		// 腾讯面试题:单链表的反转
//		System.out.printf("\n链表反转:\n");
//		ReverseLinkedList(linkedList.getHeader());
//		linkedList.showLinkedList(); //显示链表信息
		
		// 百度面试题:反向打印单链表(1.链表反转,2.放到栈里)
		// 只编写用栈实现的代码
		System.out.printf("\n使用栈进行链表反转:\n");
		stackReverseLinkedList(linkedList.getHeader());
		/**************************end*********************************/
	}
	
	// 0.1 统计单链表中的有效节点个数
	public static int getLength(HeroNode hero) { //经过static修饰过后的方法可以用类名直接调用,不用实例化一个对象后才调用
		HeroNode temp = hero;
		int length = 0;
		while(true) {
			if(temp.next==null) {
				break;
			}
			temp = temp.next;
			length++;
		}
		return length;
	}
	
	// 0.2 单链表中的倒数第k个结点 【新浪面试题】
	public static HeroNode getReverseNode(HeroNode headNode, int number) {
		HeroNode temp = headNode;
		int count = 0;
		while(true) {
			if(number == count) {
				break;
			}
			count++;
			temp = temp.next;
		}
		return temp;
	}
	
	// 0.3 单链表的反转【腾讯面试题,有点难度】
	// 除了头部head之外的节点都要反转
	public static void ReverseLinkedList(HeroNode head) {
		// 如果单链表不存在或者只有一个节点,则没有反转的必要
		if(head.next == null || head.next.next == null) {
			return;
		}else {
			// 初始化操作
			HeroNode currentNode = head.next;		  //保存node.next数据
			HeroNode nextNode = null;				  //暂存node.next.next数据
			HeroNode newHead = new HeroNode(0,"",""); //临时的一个头节点,用于在暂存反转之后的数据
			
			while(currentNode != null) {
				nextNode = currentNode.next;
				currentNode.next = newHead.next;
				newHead.next = currentNode;
				currentNode = nextNode;
			}
			
			head.next = newHead.next;
			return;
		}
	}
	
	//0.4 使用栈进行单链表的反转
	public static void stackReverseLinkedList(HeroNode head) {
		// 如果单链表不存在或者只有一个节点,则没有反转的必要
		if(head.next == null || head.next.next == null) {
			return;
		}else {
			HeroNode currentNode = head.next;		  //保存node.next数据
			Stack<HeroNode> heroStack = new Stack<HeroNode>();
			
			while(currentNode!=null) {
				heroStack.push(currentNode);
				currentNode = currentNode.next;
			}
			
			while(heroStack.size()>0) {
				System.out.println(heroStack.pop());
			}
		}
	}
}


/*
 * 2.对单链表定义“增删改查”方法
 */
class SingleLinkedList {
	
	HeroNode headNode = new HeroNode('0',"",""); //定义链表头部
	
	// 2.0 返回链表的header
	public HeroNode getHeader() {
		return headNode;
	}
	
	// 2.1 追加数据到链表尾部(不排序)
	public void addToEnd(HeroNode hero) {
		HeroNode temp = headNode; //用于暂存节点
		
		while (true) {
			if(temp.next == null) { 	// 到达链表末端,退出程序。
				break;
			}
			temp = temp.next;
		}
		
		temp.next = hero;
	}
	
	// 2.2 追加数据到链表(根据序号从小到大排序)
	public void addWithOrder(HeroNode hero) {
		HeroNode temp = headNode; //用于暂存节点
		boolean flag = true; //false代表序号重复
		while (true) {
			if(temp.next == null) { 	// 到达链表末端,退出程序。
				break;
			}
			
			// 判断有没有找到节点
			if(temp.next.number > hero.number) {
				flag = true; //已经找到节点了
				break;
			} else if(temp.next.number == hero.number) {
				flag = false;
				break;
			}
			
			temp = temp.next;
		}
		
		// 必须要到while外面去追加节点,否则在while里面会走不到加节点的那一步
		if(!flag) {
			System.out.printf("%s%d%s","error:英雄序号"+ hero.number +"已经存在");
			return;
		}
		hero.next = temp.next;
		temp.next = hero;
	}
	
	// 2.3 删除节点信息
	public void delNode(int number) {
		HeroNode temp = headNode; //用于暂存节点
		while (true) {
			if(temp.next == null) { 	// 到达链表末端,退出程序。
				break;
			}
			
			if(temp.next.number == number) {
				temp.next = temp.next.next;
			}
			
			temp = temp.next;
		}
	}
	
	// 2.4 修改节点信息
	public void reviseNode(int number, String name, String nickName) {
		HeroNode temp = headNode; //用于暂存节点
		while (true) {
			if(temp.next == null) {
				break;
			}
			
			if(temp.next.number == number) {
				temp.next.name = name;
				temp.next.nickName = nickName;
			}
			
			temp = temp.next;
		}
	}
	
	// 2.5 查看链表数据
 	public void showLinkedList() {
		HeroNode temp = headNode; //用于暂存节点
		
		while(true) {	
			if(temp.next == null) {
				break;
			}
			temp = temp.next;
			System.out.println(temp);
		}
	}
}

/*
 * 3.HeroNode->定义英雄人物。 
 * 属性:序号,名字,昵称以及下一个节点
 */
class HeroNode {
	public int number;
	public String name;
	public String nickName;
	public HeroNode next; //将new的HeroNode实例对象指向next
	
	public HeroNode(int number, String name, String nickName) {
		this.number = number;
		this.name = name;
		this.nickName = nickName;
	}
	
	@Override
	public String toString() {
		return "no."+ this.number + "---" + this.name + "---" + this.nickName;
	}
}

三、结果

四、特别说明

代码有很多,不只是解决这个问题!其中还包括了单链表的实现,单链表的增删改查;以及包含了新浪,百度,腾讯的面试题!有些题目在前面的文章里有提到,有些没有提到。有兴趣的小伙伴自行查看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
递归算法如下: 1. 定义一个单链表结构体Node,包含数据域和指向下一个节点的指针域。 2. 定义一个函数createList,用于创建单链表。该函数接收一个指向头节点的指针,以及一个整型变量n,表示需要创建的节点数。 3. 在createList函数中,首先判断n是否为0,如果是,则返回空指针;否则,创建一个新节点,将其数据域赋值为用户输入的数据,将其指针域赋值为NULL。 4. 然后递归调用createList函数,将n减1,将新节点的指针域指向递归返回的节点。 5. 最后返回新节点的指针。 6. 在主函数中,调用createList函数创建单链表,并用尾插法输入5个数据。 7. 定义一个函数reversePrint,用于反向输出单链表数据。该函数接收一个指向头节点的指针。 8. 在reversePrint函数中,首先判断当前节点是否为空,如果是,则返回;否则,递归调用reversePrint函数,输出下一个节点的数据,然后输出当前节点的数据。 完整代码如下: #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next; } Node; Node *createList(Node **head, int n) { if (n == 0) { return NULL; } Node *newNode = (Node *)malloc(sizeof(Node)); printf("请输入第%d个节点的数据:", n); scanf("%d", &newNode->data); newNode->next = NULL; newNode->next = createList(head, n - 1); if (*head == NULL) { *head = newNode; } return newNode; } void reversePrint(Node *head) { if (head == NULL) { return; } reversePrint(head->next); printf("%d ", head->data); } int main() { Node *head = NULL; createList(&head, 5); printf("反向输出单链表数据:"); reversePrint(head); printf("\n"); return 0; }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值