#include <stdio.h>
#include <stdlib.h>
//結點結構體
struct Node
{
int a;
struct Node * pNext;
};
//鏈表頭尾指針
struct Node * g_pEnd = NULL;//這裏的null沒有意義,由於在主函數開始會直接給head和end申請地址,成爲空頭
struct Node * g_pHead = NULL;
void InitListHead();
struct Node * CreatNode(int a);
void AddListTail(int a);
void AddListHead(int a);
void ScanList();
int main()
{
InitListHead();
//操做
//在這裏不能頭添加刪尾,緣由不清楚
//之後熟練以前暫時都使用有空頭尾添加
AddListTail(10);
AddListTail(20);
AddListTail(30);
AddListTail(40);
DeleteListRand(20);
ScanList();
system("Pause");
}
//空頭鏈表初始化
void InitListHead()
{
//鏈表空頭
g_pHead = (struct Node *)malloc(sizeof(struct Node)); //此時head是有地址的,成爲空頭
g_pHead->pNext = NULL;
g_pEnd = g_pHead;//剛開始的時候,end地址就是head地址,表示一個空頭結點
}
//鏈表首節點的建立
struct Node * CreatNode(int a)
{
//建立一個結點
struct Node *pTemp = (struct Node *)malloc(sizeof(struct Node));
//結點成員賦值
pTemp->a = a;
pTemp->pNext = NULL;
return pTemp;
}
//尾添加
void AddListTail(int a)
{
struct Node *pTemp = CreatNode(a);
//連接
g_pEnd->pNext = pTemp;
g_pEnd = pTemp;
}
//頭添加
void AddListHead(int a)
{
struct Node *pTemp = CreatNode(a);
//連接
pTemp->pNext = g_pHead->pNext;
g_pHead->pNext = pTemp;
}
//遍歷整個鏈表
void ScanList()
{
struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
while (pTemp)
{
printf("%d\n",pTemp->a);
pTemp = pTemp->pNext;
}
}
//查找指定結點,而且返回結點地址
struct Node * SelectNode(int index)
{
struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
while (pTemp)
{
if (index == pTemp->a)
{
return pTemp;
}
pTemp = pTemp->pNext;
}
return NULL;
}
//任意位置添加結點(根據鏈表中的某個值,在後面添加)
void AddListRank(int index, int a)
{
//判斷鏈表有沒有東西
if (NULL == g_pHead->pNext)
{
printf("鏈表無節點");
}
//找index結點
struct Node *pTemp = SelectNode(index);
if (NULL == pTemp)
{
printf("查無此結點\n");
}
//找到了,鏈接到指定位置
struct Node * pNode = CreatNode(a);
if (pNode == g_pEnd)
{
g_pEnd->pNext = pNode;
g_pEnd = pNode;
}
else
{
pNode->pNext = pTemp->pNext;
pTemp->pNext = pNode;函數
//在這裏有瑕疵,若是插入的值不是g_pEnd,能夠不修改g_pEnd的值,可是若是插入的值就在g_pEnd,則應該將g_pEnd指針指向pNode指針
/* if (NULL == NewNode->pNext)
{
g_pEnd = NewNode;
}排序
*/
}
}
//struct Node * Find(int index)
//{
// int cnt = 0;
// //判斷鏈表有沒有東西
// if (NULL == g_pHead->pNext)
// {
// printf("鏈表無節點");
// }
// //找index結點
// struct Node *pTemp = g_pHead;
// while(pTemp)
// {
// pTemp = pTemp->pNext;
// if (cnt == index)
// {
// return pTemp;
// }
// cnt++;
// }
//}
//
//void AddListNum(int a, int index)
//{
// struct Node * pNode = CreatNode(a);
// struct Node * pTemp = Find(index);
// if (pTemp == g_pEnd)
// {
// g_pEnd->pNext = pNode;
// g_pEnd = pNode;
// }
// else
// {
// pNode->pNext = pTemp->pNext;
// pTemp->pNext = pNode;
// }
//}
//刪頭
void DeleteListHead()
{
//判斷鏈表有沒有東西
if (NULL == g_pHead->pNext)
{
printf("鏈表無頭");
return;
}
struct Node * pTemp = g_pHead->pNext;
//變頭
g_pHead->pNext = g_pHead->pNext->pNext;
//釋放
free(pTemp);
}
//刪尾
void DeleteListTail()
{
//判斷鏈表有沒有東西
if (g_pHead->pNext == NULL)
{
printf("鏈表無尾");
return;
}it
//這裏用了多個if 和一個else可能會形成混亂,建議if else 在else下再if else,確保正確
//有一個結點
if (g_pHead->pNext == g_pEnd)
{
free(g_pEnd);
g_pHead->pNext = NULL;
g_pEnd = g_pHead;
}
else
{
//找到尾結點的下一個
struct Node *pTemp = g_pHead->pNext; //因爲第一個是空頭g_pHead,因此遍歷的時候直接從g_pHead指向的下一個結點開始遍歷
while (pTemp)
{
if (g_pEnd == pTemp->pNext)
{
break;
}
pTemp = pTemp->pNext;
}
//pTemp是尾巴的前一個
free(g_pEnd);
//變新尾巴
g_pEnd = pTemp;
//尾巴下一個賦值空
g_pEnd->pNext = NULL;
}
}
//刪指定結點
void DeleteListRand(int a)
{
//判斷鏈表有沒有東西
if (NULL == g_pHead->pNext)
{
printf("鏈表無節點");
}
//找index結點
struct Node *pTemp = SelectNode(a);
if (NULL == pTemp)
{
printf("查無此結點\n");
}
//找到結點
//頭,尾和中間
//找到前一個結點
//只有一個結點
if (pTemp == g_pEnd)
{
DeleteListTail();
}
else
{
struct Node *pT = g_pHead;
while (pT)
{
if(pTemp == pT->pNext)
{
break;
}
pT = pT->pNext;
}
//刪除
pT->pNext = pTemp->pNext;
//釋放
free(pTemp);
}
}
//釋放鏈表
void FreeList()
{
struct Node * pTemp = g_pHead;
while (pTemp != NULL)
{
struct Node *pT = pTemp;
pTemp = pTemp->pNext;
free(pT);
}
g_pHead = NULL;
g_pEnd = NULL;
}
io
//對鏈表進行排序List
void SortList()
{
int i, j, t;
struct Node * p = g_pHead->pNext;
struct Node * q = p->pNext;
while (p != NULL)
{
while (q != NULL)
{
if (p->a > q->a)
{
t = p->a;
p->a = q->a;
q->a = t;
}
q = q->pNext;
}
p = p->pNext;
q = p; //關鍵,若是不加則q爲NULL,若是q = p->pNext,則當q指向NULL時,p指向NULL指向的下一個,程序崩潰
}
}遍歷
刪除的思路都是:程序
先找到刪除的結點的前一個結點,而後設pT = 刪除的結點,前一個結點的指向地址變爲刪除結點指向的地址,free掉pT鏈表
特殊狀況考慮:di
刪頭:考慮找不到結點狀況; 考慮空鏈表 g_pHead->pNext == NULL; 不用考慮一個結點的狀況!!(由於直接free); 其他
刪尾:考慮找不到結點狀況; 考慮空鏈表 g_pHead->pNext == NULL; 考慮只有一個結點 g_pHead->pNext == g_pEnd; (由於找不到那個結點前面的值); 其他
刪指定:考慮找不到結點狀況; 考慮空鏈表 g_pHead->pNext == NULL; 考慮只有一個結點 g_pHead->pNext == g_pEnd; (由於找不到那個結點前面的值); 其他