#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;
}