資料結構——c實現連結串列增刪查改
阿新 • • 發佈:2019-02-01
在資料結構中,順序表和連結串列的增刪查改是基礎的知識,下邊是我學習連結串列的一些心得。
連結串列的增刪查改。(後附完整程式碼實現)
尾插:(思路:先建立一個新的結點,讓連結串列遍歷到最後一個結點,讓最後一個節點的next指向下一個newNode即可)
程式碼實現:
//尾插一個元素到連結串列中 void LinkListPushBack(LinkNode** head,LinkType value){ if(head == NULL){ return; } if(*head == NULL){ *head = CreatNewNode(value); return; } LinkNode *phead = *head; while(phead->next){ phead = phead->next; } phead->next = CreatNewNode(value); return; }
尾刪一個元素:
思路:定義兩個指標,使其遍歷連結串列,同時++,當cur->next指向為空的時候,停止,銷燬cur指向的節點。
程式碼實現:
void LinkListPopBack(LinkNode** head){ if(head == NULL){ //非法輸入 return; } if(*head == NULL){ return; //空連結串列 } if((*head)->next == NULL){ DestoryNode(*head); *head == NULL; return; } LinkNode* pre = NULL; LinkNode* cur = *head; while(cur->next != NULL){ pre = cur; cur = cur->next; } pre->next = NULL; DestoryNode(cur); return; }
頭插和頭刪:
頭插思維:建立一個新的節點,使其next指向頭結點,再將NewNode成為頭結點。
頭刪思維:將頭結點變為頭結點的下一個節點,銷燬之前的頭結點即可
程式碼實現:
//頭插一個元素 void LinkListPushHead(LinkNode** head,LinkType value){ if(head ==NULL){ return; } LinkNode* NewNode = CreatNewNode(value); NewNode->next = *head; *head = NewNode; return; } //頭刪一個元素 void LinkListPopHead(LinkNode** head){ if(head == NULL){ //非法輸入 return; } if(*head == NULL){ //空連結串列 return; } LinkNode* cur = *head; *head = (*head)->next; DestoryNode(cur); return; }
在元素之後插入元素:
與尾插的思維相差不多,但是不用遍歷,直接使其建立的節點指向就行。但是需要注意的是,需要先讓新結點指向下一個節點,不然pos的下一個知不道正確的地址。
程式碼實現:
//在下標為pos後插入值
void LinkListInsert(LinkNode* pos,LinkType value){
if(pos == NULL){
return;
}
LinkNode* NewNode = CreatNewNode(value);
NewNode->next = pos->next;
pos->next = NewNode;
return;
}
在元素之前插入元素:
思路:這個實現起來還是挺有意思的,要實現一種偷樑換柱的思維。先實現元素之後的插入,然後進行值交換,即可得到結果。
程式碼實現:
//在下標為pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
return;
//空連結串列
}
if(pos == NULL){
return;
}
LinkNode* NewNode = CreatNewNode(value);
NewNode->next = pos->next;
pos->next = NewNode;
NewNode->data = pos->data;
pos->data = value;
return;
}
後邊的查詢和刪除就直接寫程式碼了:
//實現刪除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
//空指標
return;
}
LinkNode* cur = *head;
LinkNode* pos = LinkListFind(*head,value);
for(; cur != NULL; cur = cur->next){
break;
}
if(cur == NULL){
return;
}
cur->next = pos->next;
DestoryNode(pos);
}
//刪除一個元素值出現的所有情況
void LinkListDelAll(LinkNode** head,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(head == NULL){
return;
}
LinkNode* cur = *head;
while(cur != NULL){
while(cur->data == value){
cur = cur->next;
}
*head = cur;
LinkNode* pos = *head;
cur = cur->next;
while(cur != NULL){
if(cur->data !=value){
pos->next = cur;
pos = pos->next;
}
cur = cur->next;
}
pos->next == NULL;
pos = pos->next;
DestoryNode(pos);
}
return;
}
//查詢一個元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
if(head == NULL){
return NULL;
}
LinkNode* cur = head;
for(;cur != NULL;cur=cur->next){
if(cur->data == value){
return cur;
}
}
return NULL;
}
實現完整程式碼;
LinkList.h:
#pragma once
#include<stdio.h>
typedef char LinkType; //重定義型別
typedef struct LinkNode{ //定義結構體
LinkType data; //資料域
struct LinkNode* next; //指標域
}LinkNode;
void LinkListInit(LinkNode** head); //初始化連結串列
void PrintChar(LinkNode* head,char* msg); //列印連結串列
void DestoryNode(LinkNode* node); //實現銷燬一個結點
void LinkListDestory(LinkNode** head); //實現刪除一個結點
LinkNode* CrearNewNode(LinkType value); //建立一個新結點
void LinkListPushBack(LinkNode** head,LinkType value); //尾插一個元素到連結串列中
void LinkListPosBack(LinkNode** head); //尾刪一個元素
void LinkListPushHead(LinkNode** head,LinkType value); //頭插一個元素
void LinkListPopHead(LinkNode** head); //頭刪一個元素
LinkNode* LinkListFind(LinkNode* head,LinkType value); //查詢元素值的下標
void LinkListInsert(LinkNode* pos,LinkType value); //在Pos下標後插入值
void LinkedListInsertBef(LinkNode** head,LinkNode* pos,LinkType value); //在pos> 下標前插入元素
void LiskListDelVal(LinkNode** head,LinkType value); //刪除指定元素
void LiskListDelAll(LinkNode** head,LinkType value); //刪除所有的a元素
size_t LinkListSize(LinkNode* head); //元素個數
程式碼實現:LinkList.c
#include "LinkedList.h"
#include<stdlib.h>
//初始化連結串列
void LinkListInit(LinkNode** head){
*head = NULL;
}
//實現建立一個新的結點
LinkNode* CreatNewNode(LinkType value){
LinkNode* NewNode = (LinkNode*)malloc(sizeof(LinkNode));
NewNode->data = value;
NewNode->next = NULL;
return NewNode;
}
//列印程式碼函式
void PrintChar(LinkNode* head,char* msg){
if(head == NULL){
return;
}
printf("%s\n\n",msg);
while(head){
printf("[%c]",head->data);
head=head->next;
}
printf("\n\n");
}
//實現銷燬一個結點
void DestoryNode(LinkNode* node){
if(node == NULL){
return;
}
free(node);
}
//實現刪除節點
void LinkListDestory(LinkNode** head){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
//空結點
return;
}
LinkNode* cur = *head;
while(*head !=NULL){
cur = (*head)->next;
DestoryNode(*head);
*head = cur;
}
return;
}
//尾插一個元素到連結串列中
void LinkListPushBack(LinkNode** head,LinkType value){
if(head == NULL){
return;
}
if(*head == NULL){
*head = CreatNewNode(value);
return;
}
LinkNode *phead = *head;
while(phead->next){
phead = phead->next;
}
phead->next = CreatNewNode(value);
return;
}
//尾刪一個元素
void LinkListPopBack(LinkNode** head){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
return;
//空連結串列
}
if((*head)->next == NULL){
DestoryNode(*head);
*head == NULL;
return;
}
LinkNode* pre = NULL;
LinkNode* cur = *head;
while(cur->next != NULL){
pre = cur;
cur = cur->next;
}
pre->next = NULL;
DestoryNode(cur);
return;
}
//頭插一個元素
void LinkListPushHead(LinkNode** head,LinkType value){
if(head ==NULL){
return;
}
LinkNode* NewNode = CreatNewNode(value);
NewNode->next = *head;
*head = NewNode;
return;
}
//頭刪一個元素
void LinkListPopHead(LinkNode** head){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
//空連結串列
return;
}
LinkNode* cur = *head;
*head = (*head)->next;
DestoryNode(cur);
return;
}
//在下標為pos後插入值
void LinkListInsert(LinkNode* pos,LinkType value){
if(pos == NULL){
return;
}
LinkNode* NewNode = CreatNewNode(value);
NewNode->next = pos->next;
pos->next = NewNode;
return;
}
//在下標為pos前插入值
void LinkListInsertBef(LinkNode** head,LinkNode* pos,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
return;
//空連結串列
}
if(pos == NULL){
return;
}
LinkNode* NewNode = CreatNewNode(value);
NewNode->next = pos->next;
pos->next = NewNode;
NewNode->data = pos->data;
pos->data = value;
return;
}
//查詢一個元素的值,返回地址
LinkNode* LinkListFind(LinkNode* head,LinkType value){
if(head == NULL){
return NULL;
}
LinkNode* cur = head;
for(;cur != NULL;cur=cur->next){
if(cur->data == value){
return cur;
}
}
return NULL;
}
//實現刪除指定的元素
void LinkListDelVal(LinkNode** head,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(*head == NULL){
//空指標
return;
}
LinkNode* cur = *head;
LinkNode* pos = LinkListFind(*head,value);
for(; cur != NULL; cur = cur->next){
break;
}
if(cur == NULL){
return;
}
cur->next = pos->next;
DestoryNode(pos);
}
//刪除一個元素值出現的所有情況
void LinkListDelAll(LinkNode** head,LinkType value){
if(head == NULL){
//非法輸入
return;
}
if(head == NULL){
return;
}
LinkNode* cur = *head;
while(cur != NULL){
while(cur->data == value){
cur = cur->next;
}
*head = cur;
LinkNode* pos = *head;
cur = cur->next;
while(cur != NULL){
if(cur->data !=value){
pos->next = cur;
pos = pos->next;
}
cur = cur->next;
}
pos->next == NULL;
pos = pos->next;
DestoryNode(pos);
}
return;
}
//實現元素個數
size_t LinkListSize(LinkNode* head){
if(head == NULL){
return 0;
}
LinkNode* pos = head;
size_t count = 0;
while(pos != NULL){
++count;
pos = pos->next;
}
return count;
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//********************測試程式碼************************************//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
#define FUNCTION printf("--------------------%s-------------------\n",__FUNCTION__);
//初始化
void TestInit(){
LinkNode* head;
LinkListInit(&head);
}
//測試尾插一個元素
void TestLinkListPushBack(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
PrintChar(head,"****************尾插四個元素**************");
}
//測試尾刪元素
void TestLinkListPopBack(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
PrintChar(head,"****************尾插四個元素**************");
LinkListPopBack(&head);
PrintChar(head,"****************尾刪一個元素**************");
}
//測試頭插一個元素
void TestLinkListPushHead(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushHead(&head,'d');
LinkListPushHead(&head,'c');
LinkListPushHead(&head,'b');
LinkListPushHead(&head,'a');
PrintChar(head,"****************頭插四個元素**************");
}
//測試頭刪一個元素
void TestLinkListPopHead(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushHead(&head,'d');
LinkListPushHead(&head,'c');
LinkListPushHead(&head,'b');
LinkListPushHead(&head,'a');
PrintChar(head,"****************頭插四個元素**************");
LinkListPopHead(&head);
PrintChar(head,"****************頭刪一個元素**************");
}
//測試在pos下標後插入值
void TestLinkListInsert(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushHead(&head,'d');
LinkListPushHead(&head,'c');
LinkListPushHead(&head,'b');
LinkListPushHead(&head,'a');
PrintChar(head,"****************頭插四個元素**************");
LinkNode* pos = head->next;
LinkListInsert(pos,'d');
PrintChar(head,"************插入一個元素******************");
}
//測試查詢一個元素
void TestLinkListFind(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
PrintChar(head,"****************尾插四個元素**************");
LinkNode* pos = LinkListFind(head,'a');
printf("pos except %p,actual %p\n",head->next,pos);
PrintChar(head,"****************查詢元素**************");
}
//測試在pos下標前插入一個元素
void TestLinkListInsertBef(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
PrintChar(head,"****************尾插四個元素**************");
LinkNode* pos = LinkListFind(head,'d');
LinkListInsertBef(&head,pos,'x');
PrintChar(head,"********************在d之前插入**********");
}
//測試在pos下標前插入一個元素
void TestLinkListDelVal(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'d');
PrintChar(head,"****************尾插四個元素**************");
LinkListDelVal(&head,'b');
PrintChar(head,"****************刪除元素c*****************");
}
//測試刪除所有的a元素
void TestLinkListDelAll(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'c');
PrintChar(head,"****************尾插七個元素**************");
LinkListDelAll(&head,'a');
PrintChar(head,"****************刪除所有的a元素**************");
}
//測試程式碼
void TestSize(){
LinkNode* head;
FUNCTION;
LinkListInit(&head);
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'a');
LinkListPushBack(&head,'b');
LinkListPushBack(&head,'c');
LinkListPushBack(&head,'c');
size_t ret = LinkListSize(head);
printf("szie = %d\n",ret);
}
//主函式
int main(){
TestInit();
TestLinkListPushBack();
TestLinkListPopBack();
TestLinkListPushHead();
TestLinkListPopHead();
TestLinkListInsert();
TestLinkListFind();
TestLinkListInsertBef();
TestLinkListDelVal();
TestLinkListDelAll();
TestSize();
return 0;
}
執行部分截圖: