文章目錄
下面寫的代碼可能感覺會很亂,所以加上了目錄,意在爲了引導,也就是你需要回顧哪個算法,就能夠快速定位到該位置,如果從上往下去找的話,估計腦殼也疼死了。
一、線性表的基本操作
(一)順序表的基本操作
1. 順序表的結構體
#define MAX_SIZE 30 //設置順序表最大容量
typedef struct
{
int data[MAX_SIZE]; //設置數據最大長度
int length; //設置數據當前長度
}Sqlist;
2. 順序表的查找
/*
method:
順序表的查找
param:
L 順序表
n代表要查找的元素
*/
int Find_Elem(Sqlist L, int n)
{
int result = 0; //存放所查找到匹配值的下標
for (result; result < n; result++)
{
if (L.data[result] == n)
return result;
}
return ERROR;
}
3. 順序表的插入
/*
method:
順序表的插入
param:
sqlist 要操作的順序表
pos 要插入的位置
data 要插入的數據
*/
int Insert_Elem(Sqlist* sqlist, int pos, int data)
{
int i = 0;
if (pos<0 || pos>sqlist->length || sqlist->length == MAX_SIZE) //這裏是判斷 如果 查詢位置不在線性表內,或者線性表長度滿了,則返回Error
return ERROR;
for (i = sqlist->length-1; i >= pos; i--) //這個循環將pos位置後面的元素由後往前向後挪1個位置
sqlist->data[i+1] = sqlist->data[i];
sqlist->data[pos] = data; //插入設定值
sqlist->length += 1; //線性表長度加1
return OK;
}
4. 順序表的刪除
/*
method:
順序表的刪除
param:
sqlist 要操作的順序表
pos 要刪除的位置
num 存放刪除的元素
*/
int Delete_Elem(Sqlist* sqlist, int pos,int *num)
{
int i = pos;
if (pos<0 || pos >sqlist->length)
return ERROR;
*num = sqlist->data[pos]; //得到刪除的值
for (i; i < sqlist->length; i++) //由前往後,pos位置後面的值依次往前移動
sqlist->data[i] = sqlist->data[i + 1];
sqlist->length -= 1; //線性表長度減1
return OK;
}
5. 順序表的更改
/*
method:
順序表的更改
param:
sqlist 要操作的順序表
pos 要修改的位置
num 要修改的值
*/
int Alter_Elem(Sqlist* sqlist, int pos, int num)
{
if (pos<0 || pos >sqlist->length) //判斷範圍
return ERROR;
sqlist->data[pos] = num; //更改
return OK;
}
(二)單鏈表的基本操作
1. 單鏈表的結構體
typedef struct LNODE
{
int data; //數據域
struct LNODE* next; //指針域
}LNODE;
2. 尾插法創建單鏈表
/*
method:
尾插法創建單鏈表
param:
lnode 要操作的順序表
dat 數組中存放要創建鏈表的數據
n 要創建單鏈表的長度
*/
int Create_Lnode_Tail(LNODE* lnode, int dat[], int n)
{
LNODE* p, * q;
int i = 0;
//lnode = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE)); //創造頭節點
lnode->data = NULL; //初始化頭節點
lnode->next = NULL;
p = lnode;
for (i; i < n; i++)
{
q = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE)); //創建新結點
q->data = dat[i]; //接收數組元素
p->next= q; //尾插法核心
p = p->next;
}
p->next = NULL; //表尾
Show_Lnode_data(lnode); //遍歷單鏈表元素
return OK;
}
3. 頭插法創建單鏈表
/*
method:
頭插法創建單鏈表
param:
lnode 要操作的順序表
dat 數組中存放要創建鏈表的數據
n 要創建單鏈表的長度
*/
int Create_Lnode_Head(LNODE* lnode, int dat[], int n)
{
int i = 0;
LNODE* q;
//lnode = (LNODE *)malloc(sizeof(LNODE)); //給lnode指針分配內存空間
lnode->data = NULL; //初始化頭結點
lnode->next = NULL;
for (i; i < n; i++)
{
q = (LNODE*)malloc(sizeof(LNODE)); //創建新結點
q->data = dat[i]; //接收數組元素
q->next = lnode->next; //頭插法的核心
lnode->next = q;
}
Show_Lnode_data(lnode);
return OK;
}
4. 遍歷單鏈表
/*
method:
遍歷單鏈表的數據
param:
lnode 要操作的順序表
*/
void Show_Lnode_data(LNODE* lnode)
{
LNODE* p = lnode; //p指向單鏈表的頭結點
printf("%p", lnode); //打印出來頭結點指針的地址
while (p->next != NULL) //判斷下一個結點是否爲空
{
printf("->%d", p->next->data); //打印出來鏈表中的數據
p = p->next; //遍歷單鏈表
}
printf("\n");
}
5. 合併兩個單鏈表
/*
method:
遍歷單鏈表的數據
param:
A 要操作的順序表
B 要操作的順序表
C 存放合併後的單鏈表
*/
void Merge_Lnode(LNODE* A, LNODE* B, LNODE** C) //這裏取指針的指針
{
LNODE* a = A->next, * b =B->next, * c ;
*C = A; //將A的存儲空間的地址給*C
(*C)->next = NULL;
__vcrt_free_normal(B); //釋放掉B的所佔的存儲空間
c = *C; //指針c指向頭結點C
while (a != NULL && b != NULL) //判斷這兩個結點大小
{
if (a->data > b->data)
{
c->next = b; //鏈接單鏈表
b = b->next; //取下一個結點
c = c->next; //始終表示最後一個結點的存儲空間
}
else
{
c->next = a; //鏈接單鏈表
a = a->next; //取下一個結點
c = c->next; //始終表示最後一個結點的存儲空間
}
}
if (a != NULL) c->next = a; //若鏈表a還有值,則直接填補到末尾
if (b != NULL) c->next = b; //若鏈表b還有值,則直接填補到末尾
}
(三)雙鏈表的基本操作
1. 雙鏈表結構體
typedef struct DLNODE
{
int data; //存放結點中的數據
struct DLNODE *prior; //指向前驅結點的指針
struct DLNODE* next; //指向後繼結點的指針
}DLNODE;
2. 雙鏈表初始化
/*
method:
創建雙鏈表
param:
dlnode 要操作的順序表
dat 數組中存放要創建鏈表的數據
n 要創建單鏈表的長度
*/
int Create_DLnode(DLNODE** dlnode, int dat[], int n)
{
int i = 0;
DLNODE* p,* q;
*dlnode = (DLNODE*)malloc(sizeof(DLNODE)); //爲dlnode分配內存空間
(*dlnode)->data = NULL; //初始化頭結點
(*dlnode)->next = NULL;
(*dlnode)->prior = NULL;
p = (*dlnode); //p指針指向頭結點
for (int i = 0; i < n; i++)
{
q = (DLNODE*)malloc(sizeof(DLNODE));
q->data = dat[i];
p->next = q;
q->prior = p;
p = q;
}
p->next = NULL; //表尾
return OK;
}
3. 雙鏈表的查詢
/*
method:
查詢雙鏈表數據
param:
dlnode 要操作的順序表
x 要查找的元素值
return
返回查找到的該結點
*/
DLNODE* Find_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p;
p = dlnode->next; //這裏p指針指向第一個結點
while (p != NULL) //判斷是否循環完鏈表
{
if (p->data == x) //如果該結點正是所查找數據,直接break,返回該結點
return p;
p = p->next;
}
return NULL;
}
4. 雙鏈表的插入
/*
method:
向雙鏈表插入數據
param:
dlnode 要操作的順序表
x 要插入的元素值
*/
int Insert_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p, * q;
p = dlnode->next; //p指針指向第一個結點
q = (DLNODE*)malloc(sizeof(DLNODE)); //創建一個結點,以供插入
q->data = x;
q->next = NULL;
q->prior = NULL;
while (p != NULL) //循環鏈表
{
if (p->data < q->data) //按照升序進行插入
{
if (p->next == NULL) //如果這裏爲空,則鏈表循環完,直接將該結點插入到鏈表最後方
{
p->next = q;
q->prior = p;
break;
}
else
p = p->next; //p指向下一個元素
}
else
{ //先假想一下,一鏈表從中間切開一刀
q->prior = p->prior; //先將要插入的結點兩端賦值。即:先將q的前驅,後繼進行賦值
q->next = p;
p->prior = q; //然後再將被斷開的結點的兩端進行賦值。即p的前驅,q的前驅的後繼
q->prior->next = q;
break;
}
}
return OK;
}
5. 雙鏈表的刪除
/*
method:
向雙鏈表刪除數據
param:
dlnode 要操作的順序表
x 要刪除的元素值
*/
int Delete_DLnode(DLNODE* dlnode, int x)
{
DLNODE* p;
p = dlnode->next; //p指針指向第一個結點
while (p != NULL) //循環鏈表
{
if (p->data == x) //如果找到要刪除的結點
{ //假象一下,一鏈表從中間切開一刀,將中間取出一個結點p
p->next->prior = p->prior; //然後將斷開的兩端的鏈表的前驅和後繼進行賦值,這裏指的是 p的後繼的前驅,
p->prior->next = p->next; //和 p的前驅的後繼進行賦值
__vcrt_free_normal(p);
return OK;
}
p = p->next;
}
return ERROR;
}
6. 雙鏈表的遍歷
/*
method:
遍歷雙鏈表的數據
param:
dlnode 要操作的順序表
*/
void Show_DLnode_data(DLNODE* dlnode)
{
DLNODE* p = dlnode; //p指向單鏈表的頭結點
printf("%p", dlnode); //打印出來頭結點指針的地址
while (p->next != NULL) //判斷下一個結點是否爲空
{
printf("->%d", p->next->data); //打印出來鏈表中的數據
p = p->next; //遍歷單鏈表
}
printf("\n");
}