C語言講義——鏈表完整代碼


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
	int _id;
	char s[50];
	struct Node* pre;// 指向前一個節點的地址
	struct Node* next;// 指向下一個節點的地址
};
void node_free(struct Node** q) {
	if( *q != NULL) {
		printf("free %d\n",(*q)->_id);
		free(*q);
		*q = NULL;
	}
}
void node_print(struct Node* q) {
	if (NULL == q) {
		puts("節點打印:空節點,無可打印");
		return;
	}

	printf("preview=%10d ", q->pre);
	printf("【address=%10d】 ", q);
	printf("【id=%2d】", q->_id);
	printf("next=%10d\n", q->next);
}
void chain_print(struct Node* qFirst) {
	if (qFirst == NULL) {
		puts("沒有元素可以打印");
		return;
	}
	puts("----------↓↓↓打印鏈表------------");
	// 遍歷鏈表
	struct Node* q;
	for(q = qFirst; q != NULL; q=q->next ) {
		node_print(q);
	}
	puts("----------↑↑↑打印鏈表------------");
}

/*
* 為鏈表追加節點(加在最后)
* 參數:頭節點,需要追加的節點
* 返回值:無
*/
void chain_add(struct Node* qFirst, struct Node* qAdd) {
	// 定位到鏈表頭
	struct Node* q = qFirst;
	// 只要后面(next)有節點,往后找;直到沒有next的節點(最后一個)
	for(q; q->next!= NULL; q=q->next ) {
		//node_print(q);
	}
	// 此時定位在最后一個節點,下圖1
	// 將新節點加在最后節點的后面(next)
	q->next = qAdd;// 下圖2
	qAdd->pre = q;//下圖3
}

/*
* 刪除節點
* 參數:1.頭結點 2.待刪除的結點
*		因為被刪除的結點需要置空,所以需要使用二級指針
* 返回值:-1 刪除失敗/0 刪除成功
*/
int chain_remove(struct Node** qFirst, struct Node** qRemove) {
	struct Node* qPre = NULL;
	struct Node* qNext = NULL;
	struct Node* q = *qFirst;

	// 1.輸入Check
	if(NULL == *qRemove) {
		puts("刪無可刪!");
		return -1;
	} else {
		printf("刪除節點:id=%d\n", (*qRemove)->_id);
	}

	// 2.刪除頭結點,特殊對待
	if(*qFirst == *qRemove ) {

		if((*qFirst)->next == NULL) {
			// 就一個頭結點的場合
			node_free(qFirst);
		} else { // 見下圖4
			qNext = q->next;
			node_free(qFirst);
			*qFirst = qNext;
		}
		printf("---chain_remove(頭結點):%d\n", *qFirst);
		return 0;
	}
	// 3.遍歷鏈表
	for(q; q != NULL; q=q->next ) {
		if (q == *qRemove) {
			qPre = q->pre;
			qNext = q->next;

			if (qNext!=NULL) {// 見下圖5
				qNext->pre = qPre;
				qPre->next= qNext;
			} else {
				// 尾節點的場合,見下圖6
				qPre->next= NULL;
			}
			node_free(qRemove);
			return 0;
		}
	}
}

void chain_clear(struct Node** qFirst) {
	puts("\n----------Clear------------");

	if (qFirst == NULL) {
		puts("已經是空");
		return;
	}

	// 遍歷鏈表
	//	不斷刪除第一個元素
	while(*qFirst != NULL) {
		chain_remove(qFirst,qFirst);
		printf("---chain_clear():頭結點 %d\n", *qFirst);
	}

}

struct Node* chain_get(struct Node* qFirst, int index) {
	printf("---獲取index = %d的節點:", index);
	int i = 0;
	// 遍歷鏈表
	struct Node* q = qFirst;
	for(q; q!= NULL; q=q->next,i++ ) {
		if (index == i) {
			return q;
		}
	}
	return NULL;
}

/*
* 獲取鏈表長度(即節點的個數)
* 參數:頭節點
* 返回值:鏈表長度
*/
int chain_count(struct Node* qFirst) {
	if (qFirst == NULL) {
		// 頭節點都沒有,長度為0
		return 0;
	}
	int i = 0;
	// 遍歷鏈表
	struct Node* q = qFirst;
	for(q; q != NULL; q=q->next) {
		// 順藤摸瓜,直到最后一個節點
		i++;// 找到一個就+1
	}
	return i;
}
struct Node* node_new(int id) {
	struct Node* q = (struct Node*)malloc(sizeof(struct Node));
	memset(q, 0, sizeof(struct Node));
	q->_id = id;
	return q;
}
int g_id = 1;
struct Node* qHead = NULL;
void test0Node() {
	puts("###0節點的鏈表:");
	printf("count = %d\n",chain_count(NULL));
	chain_print(NULL);
}

void testAddNode() {
	puts("\n###添加一個節點:");
	struct Node* _q = node_new(g_id++);
	chain_add(qHead, _q);
	printf("count = %d\n",chain_count(qHead));
	chain_print(qHead);
}
void test3Node() {
	testAddNode();
	testAddNode();
	testAddNode();
	chain_print(qHead);
}

void testGetNode() {
	puts("輸入需要get的節點的id");
	int nId;
	scanf("%d", &nId);
	getchar();

	struct Node* pGet;
	pGet = chain_get(qHead, nId);
	node_print(pGet);
}
void testRemoveNode() {
	puts("輸入需要刪除的節點的id");
	int nId;
	scanf("%d", &nId);
	getchar();

	struct Node* pGet;
	pGet = chain_get(qHead, nId);
	node_print(pGet);
	chain_remove(&qHead, &pGet);
}

void menu() {
	puts("***********************");
	puts("0.空鏈表打印");
	puts("1.添加1個節點");
	puts("3.添加3個節點");
	puts("4.獲取節點");
	puts("5.打印鏈表");
	puts("7.刪除節點");
	puts("8.清空節點");
	puts("9.清屏");
	puts("其它數字.退出");

	if (NULL== qHead) {
		qHead = node_new(g_id++);
		puts("生成頭結點");
	}
	puts("***********************");
}
void testMain() {
	while(1) {
		menu();
		int nSelect = 0;
		scanf("%d", &nSelect);
		getchar();
		switch(nSelect) {
			case 0:
				test0Node();
				break;
			case 1:
				testAddNode();
				break;
			case 3:
				test3Node();
				break;
			case 4:
				testGetNode();
				break;
			case 5:
				chain_print(qHead);
				break;
			case 7:
				testRemoveNode();
				break;
			case 8:
				chain_clear(&qHead);
				break;
			case 9:
				system("cls");
				break;
			default:
				return;
		}
	}
}
int main(int argc, char** argv) {
	testMain();
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM