數據結構-鏈表(3)

在(1)的基礎上增加插入和刪除的函數

插入原理:將新的節點的指針域指向插入空的下一個節點,空的上一個節點的指針域指向這個新的節點

刪除原理:要增加一個新的節點才能使刪除成立,首先讓新的節點指向下一個節點,然後刪除要刪除的節點,再讓上一個節點指向下一個節點,再刪除掉新建立的節點,保證輸出節點佔用的內存被釋放掉。

貼出代碼:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

typedef struct Node{
	int data;//數據域,這裏存放的是想要存儲的數據
	struct Node * pNext;//指針域,這裏的存放的是下一個節點的地址
}NODE, *PNODE;//用typedef函數,就是type的define,使得NODE等價於struct Node,PNODE等價於struct Node *

//聲明函數
PNODE create_list();//鏈表創建的函數,用於創建一個非循環單鏈表
int traverse_list(PNODE);//用於輸出鏈表
bool insert_list(PNODE, int, int);//用於插入
bool delete_list(PNODE, int);//用於刪除

int main(){
	PNODE pHead = NULL;//等價於 struct Node * pHead = NULL;

	pHead = create_list();//create_list()功能:創建一個非循環單鏈表,並將該鏈表的頭結點的地址賦給pHead
    insert_list(pHead, 3, 10);//插入函數使用,在第三個位置插入一個10
    traverse_list(pHead);//鏈表中數據一個一個輸出
    delete_list(pHead, 4);//刪除函數使用,刪除第四個節點
	traverse_list(pHead);//鏈表中數據一個一個輸出
	return 0;
}

PNODE create_list(){
	int len;//用來存放有效節點的個數
	int i;
	int val;//用來臨時存放用戶輸入的結點的值

	PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配了一個不存放有效數據的頭結點
	if (NULL == pHead){//這裏的寫法是一種安全的做法,如果不小心把==寫成了=,NULL=pHead是會報錯的,而pHead=NULL就會當做賦值然後返回true處理
		printf("分配失敗, 程序終止\n");
		exit(-1);
	}
	/*
        這裏設定pTail的原因是:
            鏈表的操作原理是將新的節點掛在尾節點上
            而尾節點沒有辦法表達出來
            所以增加一個pTail來作爲尾節點
            方便下面的pNew掛上去
	*/
	PNODE pTail = pHead;
	pTail->pNext = NULL;

	printf("請輸入您需要生成的鏈表節點的個數: len = ");
	scanf("%d", &len);

	for (i=0; i<len; ++i){
		printf("請輸入第%d個節點的值: ", i+1);
		scanf("%d", &val);

		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if (NULL == pNew){
			printf("分配失敗, 程序終止\n");
			exit(-1);
		}
		/*
            第一句pNew->data = val;可以放在下面四個語句的任意位置
            第二句是將pNew掛在尾節點上
            第三句是將pNew的指針域設定爲空,意思是這是新的尾節點
            第四句是將pTail變成新的尾節點,使得循環操作成立
		*/
		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}
	return pHead;
}

int traverse_list(PNODE pHead){
    //定義一個指針,從首節點開始
	PNODE p = pHead->pNext;
	//判定,若p不爲NULL,輸出p所對應節點的數據,然後指針移向下一個節點
	while (NULL != p){
		printf("%-5d", p->data);
		p = p->pNext;
	}
	printf("\n");
	return 0;
}

//insert_list函數的目的:在鏈表的第pos個節點前面增加一個節點,其數據域爲val
bool insert_list(PNODE pHead, int pos, int val){
    int i = 0;
    PNODE p = pHead;
    //將指針p移動到要插入的位置
    while(NULL!=p && i<pos-1){
        p = p->pNext;
        i++;
    }
    if(i>pos-1 || NULL==p)
        return false;
    //建立要插入的節點
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    if(NULL == pNew){
        printf("分配內存失敗\n");
        exit(-1);
    }

    pNew->data = val;
    PNODE q = p->pNext;
    p->pNext = pNew;
    pNew->pNext = q;
    return true;
}

bool delete_list(PNODE pHead, int pos){
    int i = 0;
    PNODE p = pHead;
    //將指針指向要刪除的節點
    while(NULL!=p->pNext && i<pos-1){
        p = p->pNext;
        i++;
    }
    if(i>pos-1 || NULL==p->pNext)
        return false;
    
    PNODE q = p->pNext;
    p->pNext = p->pNext->pNext;
    free(q);//釋放q指向的空間
    q = NULL;//再“釋放”掉指針q
    
    return true;
}

這裏再說一下free(q)再q=NULL的必要性

free是釋放掉q指向的空間,而q還是指向那個空間的,要把q也釋放掉,就需要再將q賦值一個NULL使得p指向0。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章