本篇文章主要針對(duì)《數(shù)據(jù)結(jié)構(gòu)》中的單鏈表编整,循環(huán)鏈表找御,循環(huán)雙鏈表的增刪查改以及一些常用算法進(jìn)行詳盡的代碼描述元镀。本代碼使用c語(yǔ)言書(shū)寫(xiě),并且通過(guò)測(cè)試霎桅∑芤桑可以直接拷貝編譯,在你的main函數(shù)中進(jìn)行測(cè)試哆档。
- 鏈表結(jié)點(diǎn)結(jié)構(gòu)定義
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
- 頭插法建立帶頭結(jié)點(diǎn)單鏈表
/**
* [CreatListHeadInsert 采用頭插法建立帶頭結(jié)點(diǎn)的單鏈表]
* @return [構(gòu)造成功返回頭結(jié)點(diǎn)的指針]
*/
LinkList CreatListHeadInsert()
{
LNode *s;
LinkList L;
int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
scanf("%d",&x);
while(x != 999)
{
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d",&x);
}
return L;
}
- 尾插法建立帶頭結(jié)點(diǎn)的單鏈表
/**
* [CreatListTailInsert 采用尾插法建立帶頭結(jié)點(diǎn)的單鏈表]
* @return [構(gòu)造成功后返回頭結(jié)點(diǎn)的指針]
*/
LinkList CreatListTailInsert()
{
LinkList L;
L = (LinkList)malloc(sizeof(LNode));
LNode *s,*r = L;
int x;
scanf("%d",&x);
while(x != 999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d",&x);
}
r->next = NULL;
return L;
}
- 依照單鏈表結(jié)點(diǎn)的儲(chǔ)存順序依次輸出單鏈表的值
/**
* [PrintList 依照順序依次打印單鏈表儲(chǔ)存的值]
* @param L [單鏈表的頭結(jié)點(diǎn)指針]
* @return [成功打印返回 1]
*/
int PrintList(LinkList L)
{
L = L->next;
while (L != NULL) {
printf("%d,",L->data);
L = L->next;
}
printf("\n");
return 1;
}
- 逆向打印單鏈表中的值
/**
* [ReversePrint 逆向輸出所有單鏈表中的值]
* @param L [傳入單鏈表所指向的下一個(gè)結(jié)點(diǎn)指針]
*/
void ReversePrint(LinkList L)
{
if(L->next != NULL)
{
ReversePrint(L->next);
}
printf("%d,",L->data);
}
- 將單鏈表中的結(jié)點(diǎn)依照結(jié)點(diǎn)值大小順序依次從大到小輸出并且依次釋放所有結(jié)點(diǎn)
/**
* [PrintIncrease 將單鏈表中的結(jié)點(diǎn)按順序依次從大到小輸出并且釋放該結(jié)點(diǎn)]
* @param L [單鏈表頭結(jié)點(diǎn)]
*/
void PrintIncrease(LinkList L)
{
LinkList preMin,p,u;
while (L->next != NULL) {
preMin = L;
p = L->next;
while (p->next != NULL) {
if(preMin->next->data > p->next->data)
{
preMin = p;
}
p = p->next;
}
printf("%d ",preMin->next->data);
u = preMin->next;
preMin->next = u->next;
free(u);
}
free(L);
}
- 查找第i個(gè)位置上單鏈表存儲(chǔ)的值
/**
* [GetElem 依照順序查找單鏈表儲(chǔ)存的值]
* @param L [單鏈表的頭指針]
* @param i [要查找的位置]
* @return [成功返回該位置的指針 L,失敗返回 NULL]
*/
LinkList GetElem(LinkList L,int i)
{
int j = 2;
LinkList p = L->next;
if(i == 1)
{
return p;
}
if(i < 0)
{
return NULL;
}
while (p && j <= i) {
p = p->next;
j++;
}
return p;
}
- 查找目標(biāo)值e 所對(duì)應(yīng)的結(jié)點(diǎn)
/**
* [LocateElem 依照目標(biāo)數(shù)據(jù)查找單鏈表儲(chǔ)存該值得結(jié)點(diǎn)]
* @param L [單鏈表的頭指針]
* @param e [查找的目標(biāo)值]
* @return [成功返回該位置的指針 L,失敗返回 NULL]
*/
LinkList LocateElem(LinkList L, int e)
{
L = L->next;
while(L && L->data != e)
{
L = L->next;
}
return L;
}
- 單鏈表結(jié)點(diǎn)的插入與刪除
/*------------------------------------------------------------------*/
/* 針對(duì)單鏈表的插入刪除過(guò)程中住闯,如果我們需要插入或者刪除單鏈表的某一指針上的數(shù)值瓜浸,除了尋找 */
/* 單鏈表的前驅(qū)結(jié)點(diǎn)澳淑,我們還可以通過(guò)將該結(jié)點(diǎn)的值與后繼結(jié)點(diǎn)值的位置進(jìn)行互換,然后刪除后繼結(jié)點(diǎn) */
/* 以使插入和刪除操作 在 O(1)時(shí)間內(nèi) 完成插佛,減少了尋找前驅(qū)結(jié)點(diǎn)消耗的時(shí)間 */
/**
* [LinkListInsert 向單鏈表目標(biāo)位置之前插入目標(biāo)數(shù)據(jù)]
* @param L [單鏈表的頭指針]
* @param i [待插入的目標(biāo)位置 i]
* @param e [待插入的目標(biāo)值 e]
* @return [插入成功返回 1杠巡,失敗返回 -1]
*/
int LinkListInsert(LinkList L, int i, int e)
{
LinkList p,s;
p = GetElem(L,i-1);
if(p == NULL)
{
return -1;
}
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
/**
* [LinkListDelete 刪除目標(biāo)位置的結(jié)點(diǎn)]
* @param L [單鏈表的頭指針]
* @param i [待刪除位置 i]
* @return [成功返回 1,失敗返回 -1]
*/
int LinkListDelete(LinkList L, int i)
{
LinkList p,q;
p = GetElem(L,i-1);
if(p == NULL)
{
return -1;
}
q = p->next;
p->next = q->next;
free(q);
return 1;
}
/*------------------------------------------------------------------*/
/**
* ? wrong program
* [RecursiveDelElem 遞歸刪除不帶頭結(jié)點(diǎn)的單鏈表中為x的結(jié)點(diǎn)]
* @param L [單鏈表的首個(gè)結(jié)點(diǎn)]
* @param x [需要?jiǎng)h除的元素 x]
*/
void RecursiveDelElem(LinkList L, int x){
LinkList p;
if(L == NULL)
{
return ;
}
if(L->data == x)
{
p = L;
L = L->next;
free(p);
RecursiveDelElem(L,x);
} else {
RecursiveDelElem(L->next,x);
}
}
- 刪除所有值為x的結(jié)點(diǎn)
/**
* [DelElem 刪除單鏈表中所有值為x的結(jié)點(diǎn)]
* @param L [單鏈表的頭結(jié)點(diǎn)]
* @param x [待刪除值為 x 的結(jié)點(diǎn)]
*/
void DelElem(LinkList L,int x) {
LinkList p;
L = L->next;
if(L == NULL)
{
return;
}
while(L != NULL)
{
if(L->data == x)
{
p = L->next;
L->data = p->data;
L->next = p->next;
free(p);
continue;
}
L = L->next;
}
return;
}
- 刪除值在某個(gè)范圍內(nèi)的所有結(jié)點(diǎn)
/**
* [DelRangeElem 刪除單鏈表中結(jié)點(diǎn)值在某個(gè)范圍的所有結(jié)點(diǎn)]
* @param L [單鏈表頭結(jié)點(diǎn)]
* @param min [刪除范圍的最小值]
* @param max [刪除范圍的最大值]
*/
void DelRangeElem(LinkList L,int min, int max) {
LinkList p;
L = L->next;
if(L == NULL || (min > max))
{
return ;
}
while(L != NULL)
{
if(L->data >=min && L->data <= max)
{
p = L->next;
L->data = p->data;
L->next = p->next;
free(p);
continue;
}
L = L->next;
}
}
- 刪除單鏈表中的首個(gè)最小值結(jié)點(diǎn)
/**
* [DeleteFirstMin 刪除單鏈表中的首個(gè)最小值]
* @param L [單鏈表的頭結(jié)點(diǎn)]
* @return [成功返回單鏈表的刪除的最小值]
*/
int DeleteFirstMin(LinkList L)
{
int tmpMin;
LinkList p,q;
L = L->next;
tmpMin = L->data;
p = L;
while(L != NULL)
{
if(L->data < tmpMin)
{
tmpMin = L->data;
p = L;
}
L = L->next;
}
q = p->next;
p->data = q->data;
p->next = q->next;
free(q);
return tmpMin;
}
- 將單鏈表逆置
/**
* [LinkListReverse 將單鏈表原地逆置]
* @param L [單鏈表的表頭結(jié)點(diǎn)]
*/
void LinkListReverse(LinkList L)
{
LinkList p,q;
p = L->next;
L->next = NULL;
while (p != NULL)
{
q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
return ;
}
- 單鏈表插入排序雇寇,返回有序單鏈表
/**
* [LinkListInsertSort 對(duì)鏈表中的元素進(jìn)行排序氢拥,返回遞增有序的單鏈表]
* @param L [單鏈表的表頭結(jié)點(diǎn)]
*/
void LinkListInsertSort(LinkList L)
{
int tmp;
LinkList p,pre,insert;
pre = L->next;
p = pre->next;
insert = L->next;
while (p != NULL)
{
if(p->data < pre->data)
{
insert = L->next;
while(insert->data < p->data)
{
insert = insert->next;
}
pre->next = p->next;
tmp = insert->data;
insert->data = p->data;
p->data = tmp;
p->next = insert->next;
insert->next = p;
}else{
pre = pre->next;
}
p = pre->next;
}
}
- 將單鏈表拆分返回兩個(gè)單鏈表A,B锨侯,其中A,B分別存儲(chǔ)源表中奇數(shù)與偶數(shù)位置元素
/**
* [SepLinkList 將單鏈表A分解成兩個(gè)單鏈表A,B,其中A中儲(chǔ)存源單鏈表A中奇數(shù)位置元素嫩海,
* B保存偶數(shù)位置元素]
* @param A [單鏈表A的頭結(jié)點(diǎn)]
* @param B [單鏈表B的頭結(jié)點(diǎn)]
*/
void SepLinkList(LinkList A,LinkList B)
{
LinkList p,insert,pre;
pre = A;
p = pre->next;
int i = 0;
while (p != NULL) {
i++;
if(i % 2 == 0)
{
insert = p;
pre->next = p->next;
insert->next = B->next;
B->next = insert;
B = B->next;
}else{
pre = pre->next;
}
p = pre->next;
}
}
- 刪除單鏈表中所有重復(fù)元素
/**
* [DelDumpElem 刪除單鏈表中所有的重復(fù)數(shù)據(jù)]
* @param L [單鏈表的頭結(jié)點(diǎn)]
*/
void DelDumpElem(LinkList L)
{
LinkList p,pre,q;
q = L->next;
while (q->next != NULL) {
pre = q;
p = pre->next;
while(p != NULL)
{
if(p->data == q->data)
{
pre->next = p->next;
free(p);
}else{
pre = pre->next;
}
p = pre->next;
}
q = q->next;
}
}
- 在有序的單鏈表中刪除所有重復(fù)元素
/**
* [DelSortDumpElem 單鏈表有序排列,刪除單鏈表中所有相同的元素]
* @param L [單鏈表的頭結(jié)點(diǎn)L]
*/
void DelSortDumpElem(LinkList L)
{
LinkList p,pre;
pre = L->next;
p = pre->next;
while (p != NULL) {
if(p->data == pre->data)
{
pre->next = p->next;
free(p);
}else{
pre = pre->next;
}
p = pre->next;
}
}