单链表的简单操作与演示
單鏈表的簡單操作與演示
單鏈表
單鏈表概念和簡單的設計
單鏈表是一種鏈式存取的數據結構,鏈表中的數據是以結點來表示的,每個結點由元素和指針構成。
元素表示數據元素的映象,就是存儲數據的存儲單元;指針指示出后繼元素存儲位置,就是連接每個結點的地址數據。
以結點的序列表示的線性表稱作線性鏈表,也就是單鏈表,單鏈表是鏈式存取的結構。
對于鏈表的每一個結點,我們使用結構體進行設計,其主要內容有:
其中,DATA數據元素,可以為你想要儲存的任何數據格式,可以是數組,可以是int,甚至可以是結構體(這就是傳說中的結構體套結構體)
NEXT為一個指針,其代表了一個可以指向的區域,通常是用來指向下一個結點,鏈表的尾部NEXT指向NULL(空),因為尾部沒有任何可以指向的空間了
故,對于一個單鏈表的結點定義,可以代碼描述成:
//定義結點類型typedefstructNode {int data; //數據類型,你可以把int型的data換成任意數據類型,包括結構體struct等復合類型structNode *next;//單鏈表的指針域} Node,*LinkedList; //Node表示結點的類型,LinkedList表示指向Node結點類型的指針類型
鏈表的初始化
初始化主要完成以下工作:創建一個單鏈表的前置節點并向后逐步添加節點,一般指的是申請結點的空間,同時對一個結點賦空值(NULL),其代碼可以表示為:
LinkedList listinit(){Node L; L=(Node)malloc(sizeof(Node)); //開辟空間 if(L==NULL){ //判斷是否開辟空間失敗,這一步很有必要printf(“申請空間失敗”);//exit(0); //開辟空間失敗可以考慮直接結束程序 } L->next=NULL; //指針指向空}
注意:一定要判斷是否開辟空間失敗,否則生產中由于未知的情況造成空間開辟失敗,仍然在繼續執行代碼,后果將不堪設想啦,因此養成這樣的判斷是很有必要的。
頭插入法創建單鏈表
利用指針指向下一個結點元素的方式進行逐個創建,使用頭插入法最終得到的結果是逆序的。如圖所示:
從一個空表開始,生成新結點,并將讀取到的數據存放到新結點的數據域中,然后將新結點插入到當前鏈表的表頭,即頭結點之后。
//頭插法建立單鏈表LinkedList LinkedListCreatH(){Node *L; L = (Node *)malloc(sizeof(Node)); //申請頭結點空間 L->next = NULL; //初始化一個空鏈表int x; //x為鏈表數據域中的數據while(scanf(“%d”,&x) != EOF) { Node *p; p = (Node *)malloc(sizeof(Node)); //申請新的結點 p->data = x; //結點數據域賦值 p->next = L->next; /將結點插入到表頭L–>|2|–>|1|–>NULL L->next = p; }return L;}
插入法創建單鏈表
如圖所示為尾插入法的創建過程。
頭插法生成的鏈表中,結點的次序和輸入數據的順序不一致。若希望兩者次序一致,則需要尾插法。
該方法是將新結點逐個插入到當前鏈表的表尾上,為此必須增加一個尾指針r, 使其始終指向當前鏈表的尾結點,代碼如下:
//尾插法建立單鏈表LinkedList LinkedListCreatT(){Node *L; L = (Node *)malloc(sizeof(Node)); //申請頭結點空間 L->next = NULL; //初始化一個空鏈表 Node *r; r = L; //r始終指向終端結點,開始時指向頭結點int x; //x為鏈表數據域中的數據while(scanf(“%d”,&x) != EOF) { Node *p; p = (Node *)malloc(sizeof(Node)); //申請新的結點 p->data = x; //結點數據域賦值 r->next = p; //將結點插入到表頭L–>|1|–>|2|–>NULL r = p; } r->next = NULL;return L;}
遍歷單鏈表如打印、修改
從鏈表的頭開始,逐步向后進行每一個元素的訪問,稱為遍歷。
對于遍歷操作,我們可以衍生出很多常用的數據操作,比如查詢元素,修改元素,獲取元素個數,打印整個鏈表數據等等。
進行遍歷的思路極其簡單,只需要建立一個指向鏈表L的結點,然后沿著鏈表L逐個向后搜索即可,代碼如下:
//便利輸出單鏈表void printList(LinkedList L){Node *p=L->next;int i=0;while§{printf(“第%d個元素的值為:%d\n”,++i,p->data); p=p->next; }}
對于元素修改操作,以下是代碼實現:
//鏈表內容的修改,在鏈表中修改值為x的元素變為為k。LinkedList LinkedListReplace(LinkedList L,int x,int k){Node *p=L->next;int i=0;while§{if(p->data==x){ p->data=k; } p=p->next; }return L;}
簡單的遍歷設計的函數只需要void無參即可,而當涉及到元素操作時,可以設計一個LinkedList類型的函數,使其返回一個操作后的新鏈表。
插入操作
鏈表的插入操作主要分為查找到第i個位置,將該位置的next指針修改為指向我們新插入的結點,而新插入的結點next指針指向我們i+1個位置的結點。
其操作方式可以設置一個前驅結點,利用循環找到第i個位置,再進行插入。
如圖,在DATA1和DATA2數據結點之中插入一個NEW_DATA數據結點:
從原來的鏈表狀態:
到新的鏈表狀態:
代碼實現如下:
//單鏈表的插入,在鏈表的第i個位置插入x的元素LinkedList LinkedListInsert(LinkedList L,int i,int x){Node *pre; //pre為前驅結點 pre = L;int tempi = 0;for (tempi = 1; tempi < i; tempi++) { pre = pre->next; //查找第i個位置的前驅結點 } Node *p; //插入的結點為p p = (Node *)malloc(sizeof(Node)); p->data = x; p->next = pre->next; pre->next = p;return L;}
刪除操作
刪除元素要建立一個前驅結點和一個當前結點,當找到了我們需要刪除的數據時,直接使用前驅結點跳過要刪除的結點指向要刪除結點的后一個結點,再將原有的結點通過free函數釋放掉。如圖所示:
代碼如下:
//單鏈表的刪除,在鏈表中刪除值為x的元素LinkedList LinkedListDelete(LinkedList L,int x) {Node *p,*pre; //pre為前驅結點,p為查找的結點。 p = L->next;while(p->data != x) { //查找值為x的元素 pre = p; p = p->next; } pre->next = p->next; //刪除操作,將其前驅next指向其后繼。 free§;return L;}
基本操作代碼
package com.ma.linked;public class DLLinkedList {//定義一個頭節點private GoodsNode head = new GoodsNode(0,"",0);//往鏈表中添加結點public void add(GoodsNode node){GoodsNode temp = head;while (true){if(temp.next == null){break;}temp = temp.next;}temp.next = node;}//根據商品的id值進行添加,從小到大依次排序public void addOrder(GoodsNode node){GoodsNode temp = head;boolean flag = false;while (true){if(temp.next == null){break;}if (temp.next.id >node.id ){break;}else if (temp.next.id == node.id){flag = true;break;}temp = temp.next;}if (flag){System.out.println("已經存在了此商品,請勿重復添加");}else {node.next = temp.next;temp.next = node;}}/** 修改結點* 1.先找到鏈表中目標結點* 2.根據新數據進行修改* 3.根據商品編號進行查找* */public void updateNode(GoodsNode node){//如果鏈表為空if (head.next == null){System.out.println("鏈表為空");return;}GoodsNode temp = head.next;boolean flag = false;while (true){if (temp == null){break;}if (temp.id == node.id){flag = true;break;}temp = temp.next;}if (flag){//真正的修改結點temp.name = node.name;temp.price = node.price;}else {System.out.println("你要修改的結點在鏈表中未找到");}}//結點刪除功能public void delNode(int id){GoodsNode temp = head;boolean flag = false;while (true){if (temp.next == null){break;}if (temp.next.id == id){flag = true;break;}temp = temp.next;}if (flag){temp.next = temp.next.next;}else {System.out.println("沒有找到要刪除的結點" );}}//查看鏈表中每一個結點元素public void list(){if (head.next == null){return;}GoodsNode temp = head.next;while (true){if (temp == null){break;}System.out.println(temp);temp = temp.next;}}} package com.ma.linked;public class GoodsNode {public int id;public String name;public double price;public GoodsNode next;public GoodsNode(int id, String name, double price) {this.id = id;this.name = name;this.price = price;}@Overridepublic String toString() {return "GoodsNode{" +"id=" + id +", name='" + name + '\'' +", price=" + price +'}';} }演示代碼
package com.ma.linked;public class LinkedTest {public static void main(String[] args) {GoodsNode goodsNode1 = new GoodsNode(1,"耐克鞋子",999.9);GoodsNode goodsNode2 = new GoodsNode(2,"阿迪鞋子",777.9);GoodsNode goodsNode3 = new GoodsNode(3,"李寧鞋子",555.9);GoodsNode goodsNode4 = new GoodsNode(4,"安踏鞋子",222.9);DLLinkedList dlLinkedList = new DLLinkedList(); // dlLinkedList.add(goodsNode1); // dlLinkedList.add(goodsNode2); // dlLinkedList.add(goodsNode3); // dlLinkedList.add(goodsNode4);dlLinkedList.addOrder(goodsNode2);dlLinkedList.addOrder(goodsNode4);dlLinkedList.addOrder(goodsNode1);dlLinkedList.addOrder(goodsNode3);dlLinkedList.add(new GoodsNode(8,"特步鞋子",333.9));dlLinkedList.addOrder(new GoodsNode(5,"鴻星爾克鞋子",111.9));dlLinkedList.updateNode(new GoodsNode(8,"特步鞋子",444.9));dlLinkedList.delNode(8);dlLinkedList.list();} });
dlLinkedList.add(new GoodsNode(8,"特步鞋子",333.9));dlLinkedList.addOrder(new GoodsNode(5,"鴻星爾克鞋子",111.9));dlLinkedList.updateNode(new GoodsNode(8,"特步鞋子",444.9));dlLinkedList.delNode(8);dlLinkedList.list();}}
總結
以上是生活随笔為你收集整理的单链表的简单操作与演示的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 桌面新建文件夹不显示缩图_如何在Wind
- 下一篇: 暗刺,高并发五个利器