生活随笔
收集整理的這篇文章主要介紹了
线性表之链式存储结构_单链表相关算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在存儲結構上,不需要連續的存儲空間,需要上一個結點的指針域 指向下一個結點即可,找到一個結點就可以找到下一個結點。
學習教材是大話數據結構,加上自己的一些個人理解。這個算法 有點繞,需要對指針 相關內容相當熟悉。通過學習感覺單鏈表相關算法還是蠻考驗C知識的和邏輯思維。
下面看代碼:
#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OK 1
typedef int EleType;
typedef int Status;
typedef struct Node Node;//鏈表元素
struct Node
{EleType data;//數據域Node * next;//指針域
};
typedef Node* LinkList;
void printLinkList(const LinkList * const list) {if (NULL ==list) {//鏈表為空printf("printLinkList error \n");return;}int i = 1;LinkList li = (*list)->next;//從頭結點后面第一個結點開始遍歷while (li)//最后一個元素沒有指向,不會進行循環。{printf("第%d元素:%d\t", i, li->data);li = li->next;i++;}printf("\n");return;
}
//創建擁有頭結點的鏈表
//頭插法創建鏈表,往鏈表中添加元素,新創建的的元素始終在頭結點后面類似 頭指針 -> 頭結點->An->An-1->An-2 ...-> A1
//元素的數據 隨機生成100以內的數字
Status creatLinkListInHead(LinkList *list,int n) {srand(time(0));//設置隨機種子,為產生隨機數做準備。//LinkList 類型 和 Node * 類型是一樣的!看最上方定義類型別名,為什么可以做呢?鏈表的頭指針 就是指向結點Node,所有鏈表類型是 Node *,只是為了更好看而已。 LinkList li=NULL;Node *node=NULL;//可以定義為 LinkList *node = NULL;int i = 0;li = (LinkList)malloc(sizeof(Node));//頭指針指向頭結點,給頭結點分配空間if (NULL == li||n<0) {//分配內存空間失敗或者鏈表元素個數非法 返回return ERROR;}li->next = NULL;//初始頭結點沒有指向for ( i = 0; i < n; i++){node = (Node*)malloc(sizeof(Node));//給結點分配空間if (NULL==node) {//給分配空間失敗 return ERROR;}node->data = rand()%100;//除以100取余的到100以內的數字,不包括100,如果含100 就需要+1node->next = li->next;//新添加的元素指針域 指向頭結點后面的結點li->next = node;//頭結點指針域 指向新增加的元素}*list = li;//通過指針 給外部鏈表賦值return OK;
}
//尾插法創建鏈表,往鏈表中添加元素,先添加的元素放前面,后添加的元素放后面,遵循先來后到的道理
Status creatLinkListInTail(LinkList *list, int n) {srand(time(0));//設置隨機種子LinkList li = NULL ;Node *node = NULL;int i = 0;li = (LinkList)malloc(sizeof(Node));if (NULL == li || n<0) {//分配內存空間失敗或元素個數非法return ERROR;}li->next = NULL;//初始頭結點指向*list = li;//給通過外部鏈表賦值,指向頭結點,此時 list 和 li 都指向頭結點。for ( i = 0; i < n; i++){node = (Node*)malloc(sizeof(Node));//給結點分配空間if (NULL == node) {//分配空間失敗 return ERROR;}node->data = rand() % 100;//除以100取余的到100以內的數字,不包括100,如果含100 就需要+1li->next = node;//新結點 放到鏈表末尾li = node;//移動鏈表指針指向最新鏈表最后一個元素,為了下次循環在鏈表末尾添加元素//temp = node;}//最后表尾元素指針域 設置NULLli->next = NULL;//*list = li;//一定要放在for循環前面,不然頭結點的內存空間沒有指向!起初l指向頭結點,但是進入for循環后l的指向發生改變要移動指向最新添加的結點元素。return OK;
}
//獲取鏈表元素數據,通過指針返回 鏈表第i個元素的 數據
//i還是按國人的順序來吧,從1開始
Status getELement(LinkList list, int position,EleType *e) {//異常情況:空指針,元素位置非法if (NULL == list || position < 1) {return ERROR;}LinkList li = list;int i = 1;while (li && i<position) {//在鏈表范圍內遍歷元素 直到 找到第position位置的 元素 i++;li = li->next;}if (NULL == li || position > i) {//超出鏈表范圍,都遍歷完鏈表還沒找到元素。return ERROR;}//通上面 while循環 當i = position 跳出循環 ,li 此時指向鏈表 第position位置的 前面一個結點。*e = li->next->data;return OK;
}
//往鏈表中第position位置 插入元素,元素數據為 e
//元素位置從1開始數
Status insertLinkList(LinkList *list,int position,EleType e) {Node *node = (Node*)malloc(sizeof(Node));//異常情況:空指針,為插入元素分配空間失敗,元素位置非法,if (NULL == list || NULL==node || position < 1) {return ERROR;}LinkList li = * list;int i = 1;while ( li && i<position) {//在鏈表范圍內遍歷元素 直到 找到第position位置的 元素 i++;li = li->next;}if (NULL == li || position > i) {//超出鏈表范圍return ERROR;}//通上面 while循環 當i = position 跳出循環 ,li 此時指向鏈表 第position位置的 前面一個結點。node->data = e;node->next = li->next;//讓 插入結點指針域指向 原來位置的結點li->next = node;//讓插入結點位置前的結點 指向插入結點return OK;
}
//在鏈表第position位置 刪除元素,通過指針返回 刪除元素的數據內容
Status delLinkListEle(LinkList *list, int position, EleType *e) {//異常情況:空指針,元素位置非法if (NULL == list || position < 1) {return ERROR;}LinkList li = *list;Node * node = NULL;int i = 1;while (li && i<position) {//在鏈表范圍內遍歷元素 直到 找到第position位置的 元素 i++;li = li->next;}if (NULL == li || position > i) {//超出鏈表范圍,都遍歷完鏈表還沒找到元素。return ERROR;}//通上面 while循環 當i = position 跳出循環 ,li 此時指向鏈表 第position位置的 前面一個結點。node = li->next;//保存要刪除元素的地址li->next = node->next;//讓刪除元素前置結點 指向 刪除元素 直接后繼結點。然后就可以釋放 刪除結點的空間了。*e = node->data;//將刪除元素數據通過指針修改返回free(node);//釋放刪除元素空間return OK;
}
//清空整個鏈表,釋放指針指向的內存
Status freeLinkList(LinkList *list) {if (NULL == list)//空指針return ERROR;//注意:頭結點不要釋放!只釋放頭結點后面的結點元素//LinkList li = *list;這樣將會把頭結點也釋放掉LinkList li = (*list)->next;//將鏈表指針指向第一個結點元素,從這個元素開始釋放Node * node = NULL;//臨時變量,指向還未釋放的元素while (li){//鏈表指針向移動指向結點元素,直到沒有后繼結點node = li->next;//保存要釋放結點 的直接后繼結點位置。 free(li);li = node;//繼續指向 未釋放結點}//將頭結點指針域設置為NULL(*list)->next = NULL;return OK;
}
int main(void) {LinkList linkList;EleType e;printf("頭插法創建鏈表結構:\n");creatLinkListInHead(&linkList, 4);printLinkList(&linkList);//先釋放 然后再用尾插法freeLinkList(&linkList);printf("尾插法創建鏈表結構:\n");creatLinkListInTail(&linkList, 4);printLinkList(&linkList);printf("第%d個位置插入%d:\n",5,100);//插入元素insertLinkList(&linkList, 5, 100);//往鏈表尾結點后面插入元素printLinkList(&linkList);printf("第%d個位置插入%d:\n", 3, 103);//插入元素insertLinkList(&linkList, 3, 103);//鏈表中間插入元素printLinkList(&linkList);//獲取元素getELement(linkList, 4, &e);printf("第%d個位置元素:%d\n", 4,e);//刪除元素delLinkListEle(&linkList, 5, &e);printf("第%d個位置刪除:%d\n", 5, e);printLinkList(&linkList);//刪除元素delLinkListEle(&linkList, 1, &e);printf("第%d個位置刪除:%d\n", 1,e);printLinkList(&linkList);//釋放整個表freeLinkList(&linkList);system("pause");return 0;
}
結果驗證截圖:
總結
以上是生活随笔為你收集整理的线性表之链式存储结构_单链表相关算法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。