国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結(jié)構(gòu)篇】手寫雙向鏈表、單向鏈表(超詳細(xì))

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)篇】手寫雙向鏈表、單向鏈表(超詳細(xì))。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

鏈表

1、基本介紹

  • 什么是鏈表?

    鏈表(Linked List)是用鏈?zhǔn)酱鎯Y(jié)構(gòu)實(shí)現(xiàn)的線性表。鏈表示意圖:

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 鏈表的組成數(shù)據(jù)域+引用域(數(shù)據(jù)域和引用域合稱結(jié)點(diǎn)或元素)

    • 數(shù)據(jù)域存放數(shù)據(jù)元素自身的數(shù)據(jù)
    • 引用域存放相鄰結(jié)點(diǎn)的地址
  • 鏈表的特點(diǎn)

    • 鏈表中元素的聯(lián)系依靠引用域

    • 具有線性結(jié)構(gòu)的特點(diǎn),鏈表所使用的邏輯結(jié)構(gòu)是線性結(jié)構(gòu)

    • 具有鏈?zhǔn)酱鎯Y(jié)構(gòu)的特點(diǎn),所使用的物理存儲結(jié)構(gòu)是鏈?zhǔn)酱鎯?/p>

  • 鏈表的分類

    • 單向鏈表:單鏈表是一種最簡的鏈表,只有一個引用域1next

      特點(diǎn):通過next可以訪問到后繼結(jié)點(diǎn),終端結(jié)點(diǎn)的引用域指向null

    • 雙向鏈表:具有兩個引用域prevnext,prev用來保存前驅(qū)結(jié)點(diǎn)的地址,next用來保存后繼結(jié)點(diǎn)的地址

      特點(diǎn):通過next可以訪問后繼結(jié)點(diǎn),終端結(jié)點(diǎn)的next指向null;通過prev可以訪問到前驅(qū)節(jié)點(diǎn),起始結(jié)點(diǎn)的prev指向null

    • 循環(huán)鏈表:循環(huán)鏈表本質(zhì)是一種特殊的單向鏈表,只是它的終端結(jié)點(diǎn)指向了開始結(jié)點(diǎn)(也就是next存放了開始結(jié)點(diǎn)的地址)

      特點(diǎn):所有結(jié)點(diǎn)都能具有前驅(qū)節(jié)點(diǎn)和后繼結(jié)點(diǎn)

  • 鏈表的使用場景:對查找速度要求不高,但對插入和刪除速度要求高時,可以使用鏈表。常見的比如:

2、單向鏈表

單向鏈表(簡稱單鏈表)有帶頭結(jié)點(diǎn)的單鏈表,也有不帶頭鏈表的單鏈表。

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 單鏈表的基本操作

    • 非空判斷:判斷鏈表中是否含有元素
    • 求表長度:獲取鏈表中所有元素的個數(shù)
    • 插入結(jié)點(diǎn):在單鏈表中添加一個新的結(jié)點(diǎn)
    • 刪除結(jié)點(diǎn):刪除單鏈表中的結(jié)點(diǎn)
    • 取表元素:更具所給索引,確定該索引所在鏈表的結(jié)點(diǎn)
    • 定位元素:根據(jù)所給值,確定該元素所在鏈表的索引號
    • 修改元素:根據(jù)所給索引,修改對應(yīng)的結(jié)點(diǎn)
    • 清空鏈表:清空鏈表中所有的元素

2.1 帶頭節(jié)點(diǎn)的單向鏈表

帶頭結(jié)點(diǎn)就是先固定一個頭節(jié)點(diǎn),用來標(biāo)識鏈表的初始位置,它的data域不存任何東西,它的next域用來第一個結(jié)點(diǎn)的地址,每次遍歷鏈表或定位結(jié)點(diǎn)都需要借助一個輔助變量temp來實(shí)現(xiàn)。

  • 插入結(jié)點(diǎn)示意圖:

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 刪除結(jié)點(diǎn)示意圖:

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 修改結(jié)點(diǎn)示意圖:

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

遍歷經(jīng)驗(yàn)總結(jié)當(dāng)我們想要進(jìn)行的操作的結(jié)點(diǎn)依賴于前一個結(jié)點(diǎn)時,比如插入刪除、修改等操作操作,就必須從head結(jié)點(diǎn)開始遍歷,否則會出現(xiàn)空指針異常;當(dāng)我們想要進(jìn)行的操作不依賴前一個結(jié)點(diǎn)時,就無須從head結(jié)點(diǎn)開始遍歷,比如根據(jù)id獲取結(jié)點(diǎn),非空判斷、獲取鏈表長度、展示鏈表等操作。

測試類
package com.hhxy.linkedlist;

import java.util.Scanner;

import com.hhxy.queue.ArrayQueue2;
/**
 * 單向鏈表測試類
 * @author ghp
 * 測試數(shù)據(jù):
 * 1 宋江 及時雨
 * 2 林沖 豹子頭
 * 3 魯智深 花和尚
 * 4 吳用 智多星
 */
public class SingleLinkedListTest {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		SingleLinkedListDemo1 sll = new SingleLinkedListDemo1();//創(chuàng)建鏈表
		OUT:
		while(true) {
			System.out.println("-------------------單向鏈表操作界面-----------------");
			System.out.println("請輸入操作指令:");
			System.out.println("0 : 退出程序");
			System.out.println("1 : 在鏈尾添加結(jié)點(diǎn)");
			System.out.println("2 : 按id從小到大的順序添加結(jié)點(diǎn)");
			System.out.println("3 : 根據(jù)id獲取結(jié)點(diǎn)");
			System.out.println("4 : 根據(jù)id刪除結(jié)點(diǎn)");
			System.out.println("5 : 獲取鏈表中元素的個數(shù)");
			System.out.println("6 : 展示鏈表中所有的元素");
			System.out.println("7 : 根據(jù)id修改結(jié)點(diǎn)");
			System.out.println("8 : 清空鏈表");
			//用于接收用戶輸入
			int id;
			String name="";
			String alias="";
			Student student = null;
			switch(sc.next()) {
			case "0": //退出程序
				System.out.println("正在退出程序~~~");
				break OUT;
			case "1": //在鏈尾添加結(jié)點(diǎn)
				System.out.println("請按照 id name alias 的格式輸入要添加的元素:");
				id = sc.nextInt();
				name = sc.next();
				alias = sc.next();
				student = new Student(id,name,alias);
				if(sll.add(student)) System.out.println("結(jié)點(diǎn):"+student+"添加成功!");
				break;
			case "2"://按id從小到大的順序添加結(jié)點(diǎn)
				System.out.println("請按照 id name alias 的格式輸入要添加的元素:");
				id = sc.nextInt();
				name = sc.next();
				alias = sc.next();
				student = new Student(id,name,alias);
				if(sll.addById(student)) System.out.println("結(jié)點(diǎn):"+student+"添加成功!");
				break;
			case "3"://根據(jù)id獲取結(jié)點(diǎn)
				System.out.println("請輸入要獲取結(jié)點(diǎn)的id號:");
				id = sc.nextInt();
				try {
					student  = sll.get(id);
					System.out.println(id+"號結(jié)點(diǎn)為:"+student);
				}catch(Exception e){
					System.out.println(e.getMessage());
				}
				break;
			case "4"://根據(jù)id刪除結(jié)點(diǎn)
				System.out.println("請輸入要刪除結(jié)點(diǎn)的id號:");
				id = sc.nextInt();
				try {
					if(sll.remove(id)) System.out.println("結(jié)點(diǎn)刪除成功!");
				}catch(Exception e) {
					System.out.println(e.getMessage());
				}
				break;
			case "5"://獲取鏈表中結(jié)點(diǎn)的個數(shù)(不包括頭節(jié)點(diǎn))
				System.out.println("鏈表中的結(jié)點(diǎn)個數(shù)為:"+sll.size());
				break;
			case "6"://展示鏈表中所有的結(jié)點(diǎn)(不包括頭節(jié)點(diǎn))
				sll.show();
				break;
			case "7"://根據(jù)id修改結(jié)點(diǎn)
				System.out.println("請按照 id name alias 的格式輸入要修改的元素:");
				student = new Student(sc.nextInt(),sc.next(),sc.next());
				try {
					if(sll.update(student)) System.out.println("修改成功");
				}catch(Exception e) {
					System.out.println(e.getMessage());
				}
				break;
			case "8"://清空鏈表
				if(sll.clear()) System.out.println("鏈表已成功清空!");
				break;
			default:
				System.out.println("請輸入有效指令!");
				break;
			}
		}
		System.out.println("程序已退出");
	}
}

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

鏈表實(shí)現(xiàn)類:
package com.hhxy.linkedlist;

//結(jié)點(diǎn)類
class Student{
	//數(shù)據(jù)域(將成員變量設(shè)置為public方便外部訪問)
	public int id;
	public String name;
	public String alias;
	//引用域
	public Student next;
	
	public Student(int id, String name, String alias) {
		this.id = id;
		this.name = name;
		this.alias = alias;
	}

	@Override
	public String toString() {
		return "[id=" + id + ", name=" + name + ", alias=" + alias + "]";
	}
}

//鏈表類
public class SingleLinkedListDemo1 {
	//初始化頭結(jié)點(diǎn)
	Student head = new Student(-99,"","");
	/**
	 * 判斷鏈表是否為空
	 * @return true表示鏈表為空
	 */
	public boolean isEmpty() {
		//因?yàn)轭^節(jié)點(diǎn)是鏈表位置的標(biāo)識,不能動,所以使用一個輔助引用來遍歷鏈表
		Student temp = head.next;
		if(temp!=null) {
			//head后面存在至少一個元素,所以鏈表不為空
			return false;
		}
		return true;
	}
	/**
	 * 在鏈尾添加結(jié)點(diǎn)
	 * @param student 待添加的結(jié)點(diǎn)
	 * @return true表示添加成功
	 */
	public boolean add(Student student) {
		//同理,因?yàn)殒湵眍^節(jié)點(diǎn)不能動。
		//注意:需要是從頭節(jié)點(diǎn)開始遍歷,因?yàn)殒湵砜赡転榭?,如果從頭節(jié)點(diǎn)后一個遍歷,當(dāng)鏈表為空時會報空指針異常
		Student temp = head;
		//遍歷尋找尾結(jié)點(diǎn)。因?yàn)閠emp=head,所以是從頭節(jié)點(diǎn)開始遍歷
		while(temp.next != null) {
			temp = temp.next;
		}
		//已找到鏈表尾結(jié)點(diǎn),進(jìn)行指向
		temp.next = student;
		return true;
	}
	/**
	 * 按照id從小到大的順序添加結(jié)點(diǎn)
	 * @param student 待添加的結(jié)點(diǎn)
	 * @return true表示添加成功
	 */
	public boolean addById(Student student) {
		Student temp = head;
		boolean flag = true;//用于判斷鏈表是加在尾結(jié)點(diǎn),還是加在結(jié)點(diǎn)之間
		while(temp.next != null) {
			if(student.id < temp.next.id) {
				//說明是添加在結(jié)點(diǎn)之間
				flag = false;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果添加的結(jié)點(diǎn)是在尾結(jié)點(diǎn)
			temp.next = student;
		}else {
			//添加的結(jié)點(diǎn)是在結(jié)點(diǎn)之間
			student.next = temp.next;//切記:先改變后一個指向,再改變前一個指向
			temp.next = student;
		}
		return true;
	}
	/**
	 * 根據(jù)id獲取結(jié)點(diǎn)
	 * @param id 
	 * @return 返回對應(yīng)id的結(jié)點(diǎn)
	 */
	public Student get(int id) {
		if(isEmpty()) {
			throw new RuntimeException("該鏈表為空!");
		}
		Student temp = head.next;
		//從head結(jié)點(diǎn)后面開始遍歷
		boolean flag = false;//判斷鏈表中是否存在待獲取的結(jié)點(diǎn)
		while(temp != null) {
			if(temp.id == id) {
				//找到id對應(yīng)的結(jié)點(diǎn)
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果找到id對應(yīng)結(jié)點(diǎn)
			return temp;
		}else {
			//如果沒有找到id對應(yīng)的結(jié)點(diǎn)
			throw new RuntimeException("待獲取的結(jié)點(diǎn)不存在!");
		}
	}
	/**
	 * 根據(jù)id刪除結(jié)點(diǎn)
	 * @param id 待刪除結(jié)點(diǎn)的id
	 * @return true表示刪除成功
	 */
	public boolean remove(int id) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		Student temp = head;//刪除結(jié)點(diǎn)需要依賴前一個結(jié)點(diǎn),所以從頭節(jié)點(diǎn)開始遍歷
		boolean flag = false;//判斷鏈表中是否存在待刪除的結(jié)點(diǎn)
		while(temp.next != null) {
			if(temp.next.id == id) {
				//找到該結(jié)點(diǎn)
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果找到了要刪除的結(jié)點(diǎn)
			temp.next = temp.next.next;
		}else {
			//如果沒有找到id對應(yīng)的結(jié)點(diǎn)
			throw new RuntimeException("待刪除的結(jié)點(diǎn)不存在!");
		}
		return true;
	}
	/**
	 * 獲取鏈表中結(jié)點(diǎn)的個數(shù)(不包括頭節(jié)點(diǎn))
	 */
	public int size() {
		Student temp = head;
		int count = 0;
        //這里雖然遍歷了頭節(jié)點(diǎn),但是沒有遍歷尾結(jié)點(diǎn)
		while(temp.next != null) {
			count++;
			temp = temp.next;
		}
		return count;
	}
	/**
	 * 展示鏈表中所有的結(jié)點(diǎn)(不包括頭節(jié)點(diǎn))
	 */
	public void show() {
		if(isEmpty()) {
			System.out.println("鏈表為空!");
			return;
		}
		//注意:不需要展示頭節(jié)點(diǎn)!
		Student temp = head;
		while(temp.next != null) {
			System.out.println(temp.next);
			temp = temp.next;
		}
	}
	/**
	 * 根據(jù)id修改結(jié)點(diǎn)
	 * @param student 待修改的結(jié)點(diǎn)
	 * @return true表示修改成功
	 */
	public boolean update(Student student) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		Student temp = head;
		boolean flag = false;//判斷鏈表是否修改成功
		while(temp.next != null) {
			if(temp.next.id == student.id) {
				//找到要修改的鏈表
				flag = true;
				student.next = temp.next.next;
				temp.next = student;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果修改成功
			return true;
		}else {
			//如果鏈表中沒有找到待刪除的結(jié)點(diǎn)
			throw new RuntimeException("鏈表中不存在該結(jié)點(diǎn)");
		}
	}
	/**
	 * 清空鏈表
	 * @return true表示清空成功
	 */
	public boolean clear() {
		/*方式一:直接將頭節(jié)點(diǎn)指向空(節(jié)約時間,但占內(nèi)存)
		 * head.next = null;
		 * 除頭節(jié)點(diǎn)以外其它結(jié)點(diǎn)存在引用,JVM不會回收結(jié)點(diǎn)內(nèi)存,仍然會占據(jù)內(nèi)存
		 * 這種清楚方法很費(fèi)內(nèi)存! 
		 */
		//方式二:將所有結(jié)點(diǎn)占據(jù)的內(nèi)存都進(jìn)行釋放(耗時,但不占內(nèi)存)
		Student2 temp = head;//這里需要從后往前遍歷,逐步去掉所有結(jié)點(diǎn)的引用,否則無法遍歷下取
		while(head.next != null) {
			for (int i = size(); i > 1; i--) {
				temp = temp.next;
			}
			temp.next = null;
		}
		return true;
	}
}

2.2 不帶頭節(jié)點(diǎn)的單向鏈表

略……邏輯思路都差不多,只是將頭節(jié)點(diǎn)換成一個頭指針

不帶頭節(jié)點(diǎn)和帶頭結(jié)點(diǎn)的主要區(qū)別:帶頭結(jié)點(diǎn)遍歷的時候、不能將頭節(jié)點(diǎn)進(jìn)行計數(shù);而不帶結(jié)點(diǎn)能夠直接進(jìn)行遍歷

本質(zhì)上兩者并沒有什么太大區(qū)別,帶頭節(jié)點(diǎn)的鏈表沒有指針,頭結(jié)點(diǎn)就相當(dāng)于頭指針,而不帶頭節(jié)點(diǎn)的鏈表是由頭指針的

注意:這里所謂的指針和結(jié)點(diǎn)其實(shí)都是結(jié)點(diǎn)對象,只是指針初始值為null,結(jié)點(diǎn)要進(jìn)行初始化

2.3 練習(xí)

  • 反轉(zhuǎn)鏈表示意圖

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 合并鏈表示意圖

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

測試類:
/**
 * 練習(xí)題1:獲取鏈表倒數(shù)第k個結(jié)點(diǎn)
 * 練習(xí)題2:將鏈表反轉(zhuǎn)
 * 練習(xí)題3:從尾到頭打印鏈表的結(jié)點(diǎn)
 * 練習(xí)題4:合并兩個有序鏈表,合并后仍然有序
 */
//測試類:
public class SingleLinkedListDemo3{
	public static void main(String[] args) {
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		SingleLinkedList sll = new SingleLinkedList();
		sll.add(node1);
		sll.add(node2);
		sll.add(node3);
		System.out.println("鏈表原始狀態(tài):");
		sll.show();
		
		System.out.println("------------------------");
		//測試1:測試獲取鏈表倒數(shù)第k個結(jié)點(diǎn)
		Node t = sll.findLastIndexNode(sll, 1);
		System.out.println(sll.findLastIndexNode(sll,1));
		System.out.println(sll.findLastIndexNode(sll,2));
		System.out.println(sll.findLastIndexNode(sll,3));
		
		System.out.println("-------------------------");
		//測試2:測試將鏈表反轉(zhuǎn)
		sll.reverset(sll);
		System.out.println("反轉(zhuǎn)后的鏈表:");
		sll.show();
		
		System.out.println("-------------------------");
		//測試3:從頭到位打印鏈表
		System.out.println("反向打印鏈表:");
		sll.reversetPrint(sll);
		
		System.out.println("-------------------------");
		//測試4:將兩個有序鏈表合并,合并后仍然有序
		SingleLinkedList list1 = new SingleLinkedList();
		SingleLinkedList list2 = new SingleLinkedList();
		Node node4 = new Node(4);
		Node node5 = new Node(5);
		Node node6 = new Node(6);
		Node node7 = new Node(7);
		Node node8 = new Node(8);
		Node node9 = new Node(9);
		Node node10 = new Node(10);
		Node node11 = new Node(11);
		
		list1.add(node4);
		list1.add(node7);
		list1.add(node8);
		list1.add(node10);
		list1.add(node11);
		System.out.println("鏈表1:");
		list1.show();
		
		System.out.println("鏈表2:");
		list2.add(node5);
		list2.add(node6);
		list2.add(node9);
		list2.show();
		
		SingleLinkedList list = new SingleLinkedList();
		list = list.combine(list1, list2);
		
		System.out.println("合并后的鏈表:");
		list.show();
	}
}

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

鏈表實(shí)現(xiàn)類:
package com.hhxy.linkedlist;

import java.util.Stack;

//結(jié)點(diǎn)類
class Node {
	int n;
	Node next;
	public Node(int n) {
		this.n = n;
	}
	@Override
	public String toString() {
		return "[n=" + n + "]";
	}
}
//鏈表類:
public class SingleLinkedList {
	//初始化頭節(jié)點(diǎn)
	public Node head = new Node(-99);
	/**
	 * 添加結(jié)點(diǎn)
	 */
	public void add(Node node) {
		Node current = head;
		while(current.next != null) {
			current = current.next;
		}
		current.next = node;
	}
	/**
	 * 獲取鏈表的長度
	 * @return
	 */
	public int size() {
		Node current = head.next;
		int count = 0;
		while(current != null) {
			count++;
			current = current.next;
		}
		return count;
	}
	/**
	 * 展示
	 */
	public void show() {
		Node current = head.next;
		while(current != null) {
			System.out.println(current);
			current = current.next;
		}	
	}
	/*--------------------核心方法-------------------------*/
	/**
	 * 尋找鏈表倒數(shù)第k個結(jié)點(diǎn)
	 * @param index
	 * @return
	 */
	public Node findLastIndexNode(SingleLinkedList sll,int index) {
		Node head = sll.head;
		if(index <0 || index>sll.size() || head.next == null) {
			return null;
		}
		Node current = head.next;
		//將指針從第二個結(jié)點(diǎn)開始往后移動index位
		for (int i = 0; i < size()-index; i++) {
			current = current.next;
		}
		return current;
	}
	/**
	 * 將鏈表反轉(zhuǎn)
	 * @param sll 待反轉(zhuǎn)的鏈表
	 */
	public void reverset(SingleLinkedList sll) {
		Node head = sll.head;
		if(head.next == null || head.next.next == null) {
			//當(dāng)前鏈表為空,或者只有一個結(jié)點(diǎn),直接返回
			return;
		}
		SingleLinkedList sllTemp = new SingleLinkedList();//創(chuàng)建一個新鏈表
		Node headTemp = sllTemp.head;
		Node temp = null;//用來存舊鏈表的引用,方便遍歷舊鏈表
		Node current = head.next;//輔助遍歷舊鏈表
		while(current != null) {
			temp = current.next;//不保存,新鏈表就會斷開,就無法進(jìn)行遍歷了
			current.next = headTemp.next;//指向新創(chuàng)建的頭結(jié)點(diǎn)的后面的結(jié)點(diǎn)
			headTemp.next = current;//新創(chuàng)建的頭結(jié)點(diǎn),指向插入的結(jié)點(diǎn)
			current = temp;//指針往后移
		}
		head.next = headTemp.next;
	}
	/**
	 * 反向打印鏈表
	 * @param sll
	 */
	public void reversetPrint(SingleLinkedList sll) {
		Node head = sll.head;
		if(head.next == null) {
			return;
		}
	/*
	  //方式一:使用findLastIndexNode方法(要先實(shí)現(xiàn)findLastIndexNode方法,不值得推薦)
		for(int i=1;i<=sll.size();i++) {
			System.out.println(sll.findLastIndexNode(sll, i));
		}
	  //方式二:使用reverset方法(要先實(shí)現(xiàn)reverset方法,并且改變了鏈表的結(jié)構(gòu),不值得推薦)
	    reverset(sll);
	    sll.show();
	*/
		//方式三:使用棧(強(qiáng)烈推薦)
		Stack<Node> stack = new Stack<>();
		Node current = head.next;
		while(current != null) {
			stack.push(current);
			current = current.next;
		}
		while(stack.size()>0) {
			System.out.println(stack.pop());
		}
	}
	/**
	 * 合并兩個有序鏈表,合并后仍然有序(這里我是默認(rèn)按從小到大排序的)
	 */
	public SingleLinkedList combine(SingleLinkedList sll1,SingleLinkedList sll2) {
		Node head1 = sll1.head.next;//用于遍歷sll1鏈表
		Node head2 = sll2.head.next;
		if(head1 == null || head2  == null) {
        	//只要有一個鏈表為空就直接返回
        	return head1 != null ? sll1 : sll2;
        }
		SingleLinkedList sll = new SingleLinkedList();//合并后的鏈表
        Node temp=sll.head;//用來給sll鏈表添加結(jié)點(diǎn)的
        while (head1 != null && head2 != null){
            if (head1.n < head2.n){
            	//鏈表1的結(jié)點(diǎn)是當(dāng)前最小結(jié)點(diǎn)
                temp.next = head1;//新鏈表連接最小結(jié)點(diǎn)
                temp = temp.next;//每新增一個結(jié)點(diǎn),temp就往后移一位,保證他在尾結(jié)點(diǎn)方便連接新結(jié)點(diǎn)
                head1 = head1.next;//鏈表1的指針也往后移一位
            }else{
            	//鏈表2的結(jié)點(diǎn)是當(dāng)前最小結(jié)點(diǎn)
                temp.next = head2;
                temp = temp.next;
                head2 = head2.next;
            }
        }
        if (head1 != null && head2 == null){
        	//經(jīng)過一一段時間的合并后,sll2的鏈表為空了,直接就將sll1鏈表后面的結(jié)點(diǎn)拼接上去
            temp.next = head1;
        }
        if (head1 == null && head2 != null){
            temp.next = head2;
        }
        return sll;
    }
	/*------------------------------------------------*/
}

3、雙向鏈表

雙向鏈表相對單向鏈表就較為簡單了,因?yàn)槊總€結(jié)點(diǎn)既能往后遍歷,又能往前遍歷 ,對于插入、刪除、修改都無需像單鏈表一樣依靠前一個結(jié)點(diǎn)。

與單鏈表的主要區(qū)別

  1. 遍歷不僅可以往前遍歷,還可以往后遍歷

  2. 插入、刪除、修改不需要依賴前一個結(jié)點(diǎn)(在鏈尾插入需要依賴尾結(jié)點(diǎn))

  3. 添加的時候,需要進(jìn)行雙向綁定!

  • 雙向鏈表插入示意圖

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 雙向鏈表刪除示意圖

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

    手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

測試類:

和單向鏈表的測試方法相同

示意圖:

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

雙向鏈表實(shí)現(xiàn)類:

其實(shí)只要理解了單向鏈表,再來看雙向鏈表就會覺得so easy??單向鏈表的方法雙向鏈表都能使用,只是添加和修改的時候,需要多修改下prev的的指向。

package com.hhxy.linkedlist.doubles;
//結(jié)點(diǎn)類
class Student2{
	public int id;
	public String name;
	public String alias;
	public Student2 prev;//指向前一個結(jié)點(diǎn)
	public Student2 next;//指向后一個結(jié)點(diǎn)
	
	public Student2(int id, String name, String alias) {
		super();
		this.id = id;
		this.name = name;
		this.alias = alias;
	}
	@Override
	public String toString() {
		return "Student [n=" + id + ", name=" + name + ", alias=" + alias + "]";
	}
}
//鏈表類
public class DoubleLinkedListDemo1 {
	//初始化頭節(jié)點(diǎn)
	public Student2 head = new Student2(-99,"","");
	/**
	 * 判斷鏈表是否為空
	 * @return true表示鏈表為空
	 */
	public boolean isEmpty() {
		//因?yàn)轭^節(jié)點(diǎn)是鏈表位置的標(biāo)識,不能動,所以使用一個輔助引用來遍歷鏈表
		 Student2 temp = head.next;
		if(temp!=null) {
			//head后面存在至少一個元素,所以鏈表不為空
			return false;
		}
		return true;
	}
	/**
	 * 在鏈尾添加結(jié)點(diǎn)
	 * @param student2 待添加的結(jié)點(diǎn)
	 * @return true表示添加成功
	 */
	public boolean add(Student2 student2) {
		//同理,因?yàn)殒湵眍^節(jié)點(diǎn)不能動。
		//注意:需要是從頭節(jié)點(diǎn)開始遍歷,因?yàn)殒湵砜赡転榭?,如果從頭節(jié)點(diǎn)后一個遍歷,當(dāng)鏈表為空時會報空指針異常
		Student2 temp = head;
		//遍歷尋找尾結(jié)點(diǎn)。因?yàn)閠emp=head,所以是從頭節(jié)點(diǎn)開始遍歷
		while(temp.next != null) {
			temp = temp.next;
		}
		//形成雙向鏈表
		temp.next = student2;
		student2.prev = temp;
		return true;
	}
	/**
	 * 按照id從小到大的順序添加結(jié)點(diǎn)
	 * @param student2 待添加的結(jié)點(diǎn)
	 * @return true表示添加成功
	 */
	public boolean addById(Student2 student2) {
		Student2 temp = head;
		boolean flag = true;//用于判斷鏈表是加在尾結(jié)點(diǎn),還是加在結(jié)點(diǎn)之間
		while(temp.next != null) {
			if(student2.id < temp.next.id) {
				//說明是添加在結(jié)點(diǎn)之間
				flag = false;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果添加的結(jié)點(diǎn)是在尾結(jié)點(diǎn)
			//形成雙向鏈表
			temp.next = student2;
			student2.prev = temp;
		}else {
			//添加的結(jié)點(diǎn)是在結(jié)點(diǎn)之間,注意要形成雙向指向
			student2.next = temp.next;//切記:先改變后一個指向,再改變前一個指向
			temp.next.prev = student2;
			//前面一根線
			temp.next = student2;
			student2.prev = temp;
		}
		return true;
	}
	/**
	 * 根據(jù)id獲取結(jié)點(diǎn)
	 * @param id 
	 * @return 返回對應(yīng)id的結(jié)點(diǎn)
	 */
	public Student2 get(int id) {
		if(isEmpty()) {
			throw new RuntimeException("該鏈表為空!");
		}
		Student2 temp = head.next;
		//從head結(jié)點(diǎn)后面開始遍歷
		boolean flag = false;//判斷鏈表中是否存在待獲取的結(jié)點(diǎn)
		while(temp != null) {
			if(temp.id == id) {
				//找到id對應(yīng)的結(jié)點(diǎn)
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果找到id對應(yīng)結(jié)點(diǎn)
			return temp;
		}else {
			//如果沒有找到id對應(yīng)的結(jié)點(diǎn)
			throw new RuntimeException("待獲取的結(jié)點(diǎn)不存在!");
		}
	}
	/**
	 * 根據(jù)id刪除結(jié)點(diǎn)
	 * @param id 待刪除結(jié)點(diǎn)的id
	 * @return true表示刪除成功
	 */
	public boolean remove(int id) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		//使用雙向鏈表可以進(jìn)行自我刪除
		Student2 temp = head.next;//刪除結(jié)點(diǎn)需要依賴前一個結(jié)點(diǎn),所以從頭節(jié)點(diǎn)開始遍歷
		boolean flag = false;//判斷鏈表中是否存在待刪除的結(jié)點(diǎn)
		while(temp != null) {
			if(temp.id == id) {
				//找到該結(jié)點(diǎn)
				flag = true;
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果找到了要刪除的結(jié)點(diǎn)
			temp.prev.next = temp.next;//前一根線
			if(temp.next != null) {//要排除最后一個結(jié)點(diǎn)的可能,否則會出現(xiàn)空指針異常
				temp.next.prev = temp.prev;//后一根線
			}
		}else {
			//如果沒有找到id對應(yīng)的結(jié)點(diǎn)
			throw new RuntimeException("待刪除的結(jié)點(diǎn)不存在!");
		}
		return true;
	}
	/**
	 * 獲取鏈表中結(jié)點(diǎn)的個數(shù)
	 * @return
	 */
	public int size() {
		Student2 temp = head;
		int count = 0;
		while(temp.next != null) {
			count++;
			temp = temp.next;
		}
		return count;
	}
	/**
	 * 展示鏈表中所有的結(jié)點(diǎn)
	 */
	public void show() {
		if(isEmpty()) {
			System.out.println("鏈表為空!");
			return;
		}
		Student2 temp = head;
		while(temp.next != null) {
			System.out.println(temp.next);
			temp = temp.next;
		}
	}
	/**
	 * 根據(jù)id修改結(jié)點(diǎn)
	 * @param student2 待修改的結(jié)點(diǎn)
	 * @return true表示修改成功
	 */
	public boolean update(Student2 student2) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		Student2 temp = head.next;
		boolean flag = false;//判斷鏈表是否修改成功
		while(temp != null) {
			if(temp.id == student2.id) {
				//找到要修改的鏈表
				flag = true;
				//后一根線
				student2.next = temp.next;
				if(temp.next!=null) {
					//排除最后一個節(jié)點(diǎn)
					temp.next.prev = student2;
				}
				//前一根線
				temp.prev.next = student2;
				student2.prev = temp.prev;
			
				
				break;
			}
			temp = temp.next;
		}
		if(flag) {
			//如果修改成功
			return true;
		}else {
			//如果鏈表中沒有找到待刪除的結(jié)點(diǎn)
			throw new RuntimeException("鏈表中不存在該結(jié)點(diǎn)");
		}
	}
	/**
	 * 清空鏈表
	 * @return
	 */
	public boolean clear() {
		/*方式一:直接將頭節(jié)點(diǎn)指向空(節(jié)約時間,但占內(nèi)存)
		 * head.next = null;
		 * 除頭節(jié)點(diǎn)以外其它結(jié)點(diǎn)存在引用,JVM不會回收結(jié)點(diǎn)內(nèi)存,仍然會占據(jù)內(nèi)存
		 * 這種清楚方法很費(fèi)內(nèi)存! 
		 * return true;
		 */
		//方式二:將所有結(jié)點(diǎn)占據(jù)的內(nèi)存都進(jìn)行釋放(耗時,但不占內(nèi)存)
		Student2 temp = head;//這里需要從后往前遍歷,逐步去掉所有結(jié)點(diǎn)的引用,否則無法遍歷下取
		Student2 current = head;
		while(current.next != null) {
			current = temp;
			current.next = null;
			current.prev = null;
			temp = temp.next;
		}
		return true;
	}
}

4、單向環(huán)形鏈表

基本和單向鏈表類似,也可以分為帶頭節(jié)點(diǎn),和不帶頭結(jié)點(diǎn)點(diǎn),這里演示的是不帶頭結(jié)點(diǎn)的單向環(huán)形鏈表,單向環(huán)形鏈表和單向鏈表唯一的區(qū)別:尾結(jié)點(diǎn)的next不指向空,而是指向開始節(jié)點(diǎn)。

主要思想還是在單鏈表那一節(jié)??只要掌握單向鏈表,這些雙向鏈表還有單向循環(huán)鏈表就是弟弟(′д` )…彡…彡直接套用第一節(jié)的接口,實(shí)現(xiàn)所有的方法

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

測試類

和2.1一樣,換個對象就行了(這個測試類真渣??)

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

實(shí)現(xiàn)類

這里主要記錄以下按順序插入結(jié)點(diǎn)的思路,怕以后忘記了。其實(shí)主要思想還是和單向鏈表的addById方法的邏輯是一致的,主要是要考慮循環(huán)!思路主要如下:

  1. 先將鏈表添加分為兩大類,首結(jié)點(diǎn)的添加非首結(jié)點(diǎn)的添加,因?yàn)槭捉Y(jié)點(diǎn)的添加需要自動成環(huán)
  2. 再將非首結(jié)點(diǎn)的添加又分為在 添加在首結(jié)點(diǎn)之前之后,之前需要移動first指針,之后不需要移動

示意圖:

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

刪除結(jié)點(diǎn):

  1. 先將刪除分為兩大類,刪除頭結(jié)點(diǎn)刪除普通結(jié)點(diǎn)
  2. 刪除頭結(jié)點(diǎn)又可以分為兩類,鏈表只有一個頭結(jié)點(diǎn)除了頭結(jié)點(diǎn)還有其它結(jié)點(diǎn)
  3. 刪除普通結(jié)點(diǎn)時需要注意鏈表是單向的,刪除操作需要依賴待刪除結(jié)點(diǎn)的前一個結(jié)點(diǎn)

修改結(jié)點(diǎn)的邏輯思路和刪除類似,不在贅述,示意圖:

手寫雙向鏈表,算法與數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu),鏈表

  • 清空鏈表:鏈表的清空有兩種方法,一種是直接讓first=null,這種清空簡單省事,但是是假清空,鏈表仍然存在內(nèi)存中!

    第二種方法是讓每個結(jié)點(diǎn)的next指向空,然后將first=null,這種費(fèi)腦子但是省空間

package com.hhxy.linkedlist.circular;


//結(jié)點(diǎn)類
class Student{
	public int id;
	public String name;
	public String alias;
	public Student next;
	
	public Student(int id, String name, String alias) {
		super();
		this.id = id;
		this.name = name;
		this.alias = alias;
	}

	@Override
	public String toString() {
		return "[id=" + id + ", name=" + name + ", alias=" + alias + "]";
	}
}

//鏈表類
public class CircularLinkedListDemo1 {
	private Student first = null;//注意這是頭指針,不是頭結(jié)點(diǎn)!
	
	/**
	 * 非空判斷
	 * @return true表示為空
	 */
	public boolean isEmpty() {
		//因?yàn)槭菦]有頭結(jié)點(diǎn),所以直接判斷first
		if(first != null) {
			return false;
		}else {
			return true;
		}
	}
	/**
	 * 在尾結(jié)點(diǎn)添加結(jié)點(diǎn)
	 * @param student
	 * @return true表示結(jié)點(diǎn)添加成功
	 */
	public boolean add(Student student) {
		if(first == null) {
			//對第一個結(jié)點(diǎn)進(jìn)行單獨(dú)考慮
			first =  student;
			first.next = first;//構(gòu)成環(huán)狀
			return true;
		}else {
			Student current = first;
			//找到最后一個結(jié)點(diǎn)
			while(current.next != first) {
				current = current.next;
			}
			//找到后將節(jié)點(diǎn)加入環(huán)形鏈表中
			current.next = student;
			student.next = first;
			return true;
		}
	}
	/**
	 * 根據(jù)id從小到大的順序添加結(jié)點(diǎn)
	 * @return true表示添加成功
	 */
	public boolean addById(Student student) {
		if(first == null) {
			//第一個結(jié)點(diǎn)單獨(dú)成環(huán)
			first = student;
			first.next = first;
		}else {
			Student current = first;
			if(student.id < current.id && current == first) {
				//說明這個結(jié)點(diǎn)比頭結(jié)點(diǎn)還要小,要將頭指針移動位置
				current.next = student;
				student.next = current;
				first = student;//將first移動到student上
				return true;
			}
			while(current.next != first) {
				//尋早結(jié)點(diǎn)添加的位置
				if(student.id < current.next.id) {
					//已找到添加的位置
					break;
				}
				current = current.next;
			}
			student.next = current.next;//切記:一定要先改變后一根線,不然鏈表會斷裂!
			current.next = student;
		}
		return true;
	}
	/**
	 * 根據(jù)id獲取結(jié)點(diǎn)
	 */
	public Student get(int id) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		Student current = first;
		boolean flag = false;
		while(true) {
			if(current.id == id) {
				//找到就直接結(jié)束遍歷
				flag = true;
				break;
			}
			if(current.next == first) {
				//如果是最后一個結(jié)點(diǎn),就表明還沒有找到,直接結(jié)束遍歷
				break;
			}
			current = current.next;//輔助指針后移,遍歷鏈表
		}
		if(flag) {
			//找到就返回這個結(jié)點(diǎn)
			return current;
		}else {
			//沒有找到,打印提示信息
			throw new RuntimeException("鏈表中不存在該結(jié)點(diǎn)!");
		}
	}
	/**
	 * 根據(jù)id刪除結(jié)點(diǎn)
	 */
	public boolean remove(int id) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		if(first.id == id) {
			//當(dāng)頭結(jié)點(diǎn)就是要刪除的結(jié)點(diǎn)時,分類討論
			if(first.next == first) {
				//如果鏈表只有頭結(jié)點(diǎn)時
				first = null;
				return true;
			}else {
				//如果鏈表除了頭結(jié)點(diǎn)還有其它結(jié)點(diǎn)時,需要移動first指針
				Student current = first;
				//找到尾結(jié)點(diǎn)
				while(current.next != first) {
					current = current.next;
				}
				current.next = current.next.next;
				first = current.next;//移動頭指針
				return true;
			}
		}
		//刪除普通結(jié)點(diǎn)
		Student current = first;
		boolean flag = false;//判斷鏈表中是否存在該結(jié)點(diǎn)
		while(true) {
			if(current.next.id == id) {//這里使用current.next判斷是為了使用前一個結(jié)點(diǎn)
				//找到結(jié)點(diǎn)直接退出
				flag = true;
				break;
			}
			if(current.next == first) {
				//遍歷完成,直接退出
				break;
			}
			current = current.next;
		}
		if(flag) {
			//找到待刪除的結(jié)點(diǎn),利用前一個結(jié)點(diǎn)將其刪除(思路和單項(xiàng)鏈表是一樣的)
			current.next = current.next.next;
			return true;
		}else {
			throw new RuntimeException("該結(jié)點(diǎn)不存在!");
		}
	}
	/**
	 * 獲取鏈表長度
	 */
	public int size() {
		Student current = first;
		if(isEmpty()) {
			return 0;//這里要不要都無所謂,只是習(xí)慣了~~~
		}
		int count = 0;
		while(true) {
			count++;
			if(current.next == first) {
				break;
			}
			current = current.next;
		}
		return count;
	}
	/**
	 * 展示鏈表
	 */
	public void show() {
		Student current = first;
		if(first == null) {
			//排除空鏈表
			throw new RuntimeException("鏈表為空!");
		}
		while(true) {
			System.out.println(current);
			if(current.next == first) {
				//當(dāng)發(fā)現(xiàn)結(jié)點(diǎn)是最后一個結(jié)點(diǎn)直接退出打印
				break;
			}
			current = current.next;
		}
	}
	/**
	 * 根據(jù)id修改結(jié)點(diǎn)
	 */
	public boolean update(Student student) {
		if(isEmpty()) {
			throw new RuntimeException("鏈表為空!");
		}
		if(student.id == first.id) {
			//修改的結(jié)點(diǎn)是頭節(jié)點(diǎn)
			if(first.next == first) {
				//只有一個頭節(jié)點(diǎn)
				first = student;
				first.next = student;
				return true;
			}else {
				//除了頭節(jié)點(diǎn)還有其它結(jié)點(diǎn)
				Student current = first;
				//找到尾結(jié)點(diǎn)
				while(current.next != first) {
					current = current.next;
				}
				student.next = current.next.next;//修改后一根線
				current.next = student;//修改前一根線
				first = student;//修改頭指針
				return true;
			}
		}
		//修改的結(jié)點(diǎn)是普通結(jié)點(diǎn)
		Student current = first;
		boolean flag = false;//判斷鏈表中是否存在該結(jié)點(diǎn)
		while(current.next != first) {
			if(current.next.id == student.id) {
				//找到結(jié)點(diǎn),直接退出
				flag = true;
				break;
			}
			current = current.next;
		}
		if(flag) {
			student.next = current.next.next;//修改后一根線,防止鏈表斷裂
			current.next = student;
			return true;
		}else {
			throw new RuntimeException("不存在該結(jié)點(diǎn)!");
		}
	}
	/**
	 * 	清空鏈表
	 */
	public boolean clear() {
		/*方式一:直接將頭節(jié)點(diǎn)指向空(節(jié)約時間,但占內(nèi)存)
		 * first.next = null;
		 * 除頭節(jié)點(diǎn)以外其它結(jié)點(diǎn)存在引用,JVM不會回收結(jié)點(diǎn)內(nèi)存,仍然會占據(jù)內(nèi)存
		 * 這種清楚方法很費(fèi)內(nèi)存! 
		 * return true;
		 */
		//方式二:將所有結(jié)點(diǎn)占據(jù)的內(nèi)存都進(jìn)行釋放(耗時,但不占內(nèi)存)
		if(isEmpty()) {
			return true;
		}
		if(first == first.next) {
			//只有一個結(jié)點(diǎn)
			first = null;
			return true;
		}
		Student temp = first;//臨時存儲current的引用,輔助遍歷
		Student current = first;
		//將鏈表每個結(jié)點(diǎn)的引用都斷開,這樣每個結(jié)點(diǎn)都沒有被引用,就能被JVM給回收
		while(current.next != first) {
			temp = temp.next;
			current.next = null;
			current = temp;
		}
		//將最后一個結(jié)點(diǎn)的引用 和頭指針 設(shè)為空
		current.next = null;//不斷開最后一個接待你的引用,頭節(jié)點(diǎn)就不會被回收
		first = null;
		return true;
	}
}

  1. 引用域:是鏈表結(jié)點(diǎn)中一片很小的空間,用來存放后繼結(jié)點(diǎn)的地址 ??文章來源地址http://www.zghlxwxcb.cn/news/detail-677490.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)篇】手寫雙向鏈表、單向鏈表(超詳細(xì))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【數(shù)據(jù)結(jié)構(gòu)】—C語言實(shí)現(xiàn)雙向鏈表(超詳細(xì)!)

    【數(shù)據(jù)結(jié)構(gòu)】—C語言實(shí)現(xiàn)雙向鏈表(超詳細(xì)!)

    ??????????????????????????????? ??? ? 食用指南:本文在有C基礎(chǔ)的情況下食用更佳 ? ????????????????????????????? ??? ? ?? 這就不得不推薦此專欄了:C語言 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 雙向鏈表 前 置知識 :單鏈表 ? ? ?

    2024年02月13日
    瀏覽(21)
  • 數(shù)據(jù)結(jié)構(gòu)-雙向鏈表(c++)超全超詳細(xì)

    數(shù)據(jù)結(jié)構(gòu)-雙向鏈表(c++)超全超詳細(xì)

    單鏈表結(jié)點(diǎn)中只有一個指向其后繼的指針,使得單鏈表只能從頭結(jié)點(diǎn)依次順序地向后遍歷。要訪問某個結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)(插入,刪除操作時),只能從頭開始遍歷,訪問后繼結(jié)點(diǎn)的時間復(fù)雜度為O(1),訪問前驅(qū)結(jié)點(diǎn)的時間復(fù)雜度為O(n)。 提示:以下是本篇文章正文內(nèi)容,下面案

    2023年04月08日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu) —— 雙向鏈表(超詳細(xì)圖解 & 接口函數(shù)實(shí)現(xiàn))

    數(shù)據(jù)結(jié)構(gòu) —— 雙向鏈表(超詳細(xì)圖解 & 接口函數(shù)實(shí)現(xiàn))

    數(shù)據(jù)結(jié)構(gòu) —— 順序表 數(shù)據(jù)結(jié)構(gòu) —— 單鏈表 數(shù)據(jù)結(jié)構(gòu) —— 雙向鏈表 數(shù)據(jù)結(jié)構(gòu) —— 隊列 數(shù)據(jù)結(jié)構(gòu) —— 棧 數(shù)據(jù)結(jié)構(gòu) —— 堆 數(shù)據(jù)結(jié)構(gòu) —— 二叉樹 數(shù)據(jù)結(jié)構(gòu) —— 八大排序 數(shù)據(jù)結(jié)構(gòu)是計算機(jī)存儲、組織數(shù)據(jù)的方式。數(shù)據(jù)結(jié)構(gòu)是指相互之間存在一種或多種特定關(guān)系的數(shù)據(jù)元

    2024年02月11日
    瀏覽(30)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】 - 雙向鏈表 - 詳細(xì)實(shí)現(xiàn)思路及代碼

    【數(shù)據(jù)結(jié)構(gòu)與算法】 - 雙向鏈表 - 詳細(xì)實(shí)現(xiàn)思路及代碼

    前幾篇文章介紹了怎樣去實(shí)現(xiàn)單鏈表、單循環(huán)鏈表, 這篇文章主要介紹 雙向鏈表 以及實(shí)現(xiàn)雙向鏈表的步驟,最后提供我自己根據(jù)理解實(shí)現(xiàn)雙向鏈表的C語言代碼 。跟著后面實(shí)現(xiàn)思路看下去,應(yīng)該可以看懂代碼,看懂代碼后,就對雙向鏈表有了比較抽象的理解了,最后自己再

    2024年02月01日
    瀏覽(26)
  • 【數(shù)據(jù)結(jié)構(gòu)】單向鏈表

    【數(shù)據(jù)結(jié)構(gòu)】單向鏈表

    哈嘍,大家好,今天我們學(xué)習(xí)的是數(shù)據(jù)結(jié)構(gòu)里的鏈表,這里主要講的是不帶哨兵衛(wèi)頭節(jié)點(diǎn)的單向鏈表,下篇將會繼續(xù)帶大家學(xué)習(xí)雙向鏈表。 目錄 1.鏈表的概念 2.單向鏈表接口的實(shí)現(xiàn) 2.1動態(tài)申請一個節(jié)點(diǎn) 2.2單鏈表打印 2.3單鏈表尾插 2.4單鏈表頭插 2.5單鏈表尾刪 2.6單鏈表頭刪

    2024年02月11日
    瀏覽(26)
  • 數(shù)據(jù)結(jié)構(gòu)——實(shí)現(xiàn)單向鏈表

    數(shù)據(jù)結(jié)構(gòu)——實(shí)現(xiàn)單向鏈表

    單鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu),用于存儲一系列的數(shù)據(jù)元素,每個節(jié)點(diǎn)包含數(shù)據(jù)和指向下一個節(jié)點(diǎn)的指針。 單鏈表通常用于實(shí)現(xiàn)某些算法或數(shù)據(jù)結(jié)構(gòu),如鏈?zhǔn)角跋蛐?、哈希表、鏈?zhǔn)綏!㈥犃械鹊取?單鏈表在程序設(shè)計中的作用不可忽略,是很多基礎(chǔ)算法的核心數(shù)據(jù)結(jié)構(gòu)之一。

    2024年02月07日
    瀏覽(23)
  • 【數(shù)據(jù)結(jié)構(gòu)】動圖詳解單向鏈表

    【數(shù)據(jù)結(jié)構(gòu)】動圖詳解單向鏈表

    目錄 1.什么是鏈表 ? ? ? ? 1.問題引入 ? ? ? ? 2. 鏈表的概念及結(jié)構(gòu) ? ? ? ? 3. 問題解決 2.單向鏈表接口的實(shí)現(xiàn) ????????1.接口1,2---頭插,尾插 ????????2. 接口3,4---頭刪,尾刪 ????????3. 接口5---查找 ?????????4. 接口6,7---插入,刪除 ????????5.?接口

    2024年01月18日
    瀏覽(27)
  • 數(shù)據(jù)結(jié)構(gòu)與算法(三):單向鏈表

    數(shù)據(jù)結(jié)構(gòu)與算法(三):單向鏈表

    鏈表是一種物理存儲單元上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯是通過鏈表種的指針鏈接次序?qū)崿F(xiàn)的。鏈表由一系列節(jié)點(diǎn)組成,每個節(jié)點(diǎn)包括兩部分:一個是存儲數(shù)據(jù)元素的數(shù)據(jù)域,一個是存儲下一個節(jié)點(diǎn)地址的指針域。單向鏈表從頭節(jié)點(diǎn)(也可以沒有頭節(jié)點(diǎn))開始

    2024年02月15日
    瀏覽(28)
  • 【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表 超詳細(xì) (含:何時用一級指針或二級指針;指針域的指針是否要釋放)

    【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表 超詳細(xì) (含:何時用一級指針或二級指針;指針域的指針是否要釋放)

    目錄 一、簡介 二. 雙鏈表的實(shí)現(xiàn) 1.準(zhǔn)備工作及其注意事項(xiàng) 1.1 先創(chuàng)建三個文件 1.2 注意事項(xiàng):幫助高效記憶 1.3? ?關(guān)于什么時候 用 一級指針接收,什么時候用 二級指針接收? 1.4 釋放節(jié)點(diǎn)時,要將節(jié)點(diǎn)地址 置為NULL,難道 節(jié)點(diǎn)內(nèi)部的 指針域的指針 就不用置為 NULL嗎?? 2.雙鏈

    2024年02月20日
    瀏覽(27)
  • 數(shù)據(jù)結(jié)構(gòu)——單向鏈表(C語言版)

    在數(shù)據(jù)結(jié)構(gòu)和算法中,鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu),它由一系列節(jié)點(diǎn)組成,每個節(jié)點(diǎn)包含數(shù)據(jù)和指向下一個節(jié)點(diǎn)的指針。在C語言中,我們可以使用指針來實(shí)現(xiàn)單向鏈表。下面將詳細(xì)介紹如何用C語言實(shí)現(xiàn)單向鏈表。 目錄 1. 定義節(jié)點(diǎn)結(jié)構(gòu)體 2. 初始化鏈表 3. 插入節(jié)點(diǎn) 4. 刪除節(jié)點(diǎn)

    2024年03月24日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包