C語言【微專案15】—陣列-鏈表聯合結構[一種復合資料結構的探索](采用指標陣列實作數-鏈結構)【2022-01-03】
- 一、ArrayLinkList.c
- 二、 運行結果示例
【TDTX】
【C99】
【特注:資料結構使用探索分享】
【編譯與運行環境】64位Windows作業系統,TDM-gcc 4.9.2 64bit編譯,
【問題描述】讓鏈表可以如同陣列一樣查找方便(修改某結點資料域方便),讓陣列如同鏈表一樣添加和洗掉元素方便,
【數-鏈結構】(Array-Link)具有陣列特性和鏈表特性,具有陣列形態操作、鏈表形態操作,
【注】 在C語言【微專案14】中已經初步使用了該思想的雛形,現在將其整理成為一種資料結構的完整操作實作,
【思路】
1.在初始化鏈表的同時,初始化一個指標陣列,陣列長度是1,該陣列0位置存放單鏈表頭結點的地址,
2.在使用尾插法建立鏈表有效結點時,凡新生成一個結點且入鏈表立即使用realloc函式重新分配空間,使陣列長度剛好等于頭結點+有效結點的個數,再將陣列最后一個位置放上剛入鏈的結點地址,
4.在任意合法位置插入結點時,先將指標陣列空間增大一個,結點入鏈完成后,將指標陣列對應的位置空出來(將其余元素向后挪動)放上該入鏈結點的地址,
5.在任意合法位置洗掉結點時,通過指標陣列完成鏈表指向更改,最后使陣列長度減1(realloc重新分配大小),
6.在查找或獲取值時,直接通過陣列形態操作即可(通過指標陣列),
7.在遍歷【數-鏈】結構時,只需通過其陣列形態遍歷即可,也可通過其鏈表形態遍歷,
一、ArrayLinkList.c
#include <stdio.h>
#include <stdlib.h>
typedef struct Lnode
{
int data;
struct Lnode* next;
}Lnode;
typedef struct SingleLinkList
{
int len;//鏈表有效結點個數記錄
Lnode* H;//鏈表形態
int Alen;//陣列長度記錄(頭結點+有效結點)
Lnode** LAAP;//陣列形態的實作,指標陣列
}SLinkList;
int init_ArraySLinkList(SLinkList* S)
{
S->H = (Lnode*)malloc(sizeof(Lnode)*1);
S->LAAP = (Lnode**)malloc(sizeof(Lnode*)*1);
if(S->H == NULL || S->LAAP == NULL)
{
S->len = -1;
S->Alen = -1;
return 0;
}
(S->LAAP)[0] = S->H;
(S->H)->data = -1;
S->len = 0;
S->Alen = 1;
(S->H)->next = NULL;
puts("初始化【數-鏈】結構成功!");
return 1;
}
int Tail_ArraySLinkList(SLinkList* S)
{
Lnode* p = S->H;
puts("\n開始尾插法建立鏈表-輸入結點值(空格分隔,f結束):");
while(1)
{
int tdata,i;
Lnode* t;
i = scanf("%d",&tdata);
if(i == 0)
{
break;
}
//printf("tdata = %d\n",tdata);
t = (Lnode*)malloc(sizeof(Lnode)*1);
S->LAAP = (Lnode**)realloc(S->LAAP,sizeof(Lnode*)*(S->Alen+1));
if(t != NULL && S->LAAP != NULL)
{
t->data = tdata;
t->next = p->next;
p->next = t;
p = t;
(S->len)++;
(S->Alen)++;
//printf("\nS->Alen = %d\n",S->Alen);
S->LAAP[S->Alen - 1] = t;
//Traverse_SLinkList(S);
}
}
}
int Insert_ArraySLinkList(SLinkList* S,int i,int e)
{
if(S->H == NULL)
{
return -1;
}
if(i < 1 || i > S->len + 1)
{
puts("\n插入元素結點位置不合法!");
return 0;
}
Lnode* p = S->H;
Lnode* t;
int co = -1;
t = (Lnode*)malloc(sizeof(Lnode)*1);
S->LAAP = (Lnode**)realloc(S->LAAP,sizeof(Lnode*)*(S->Alen+1));
if(t == NULL || S->LAAP == NULL)
{
puts("\n待插入結點失敗!");
return 0;
}
t->data = e;
while(p != NULL)
{
co++;
if(co == i - 1)
{
t->next = p->next;
p->next = t;
(S->len)++;
(S->Alen)++;
for(int k = S->Alen - 1;k - 1 >= 0;k--)
{
if(k == i)
{
(S->LAAP)[k] = t;
break;
}
(S->LAAP)[k] = (S->LAAP)[k - 1];
}
return 1;
}
p = p->next;
}
return 1;
}
int Delete_ArraySLinkList(SLinkList* S,int i,int* e)
{
if(S->H == NULL)
{
return -1;
}
if(i < 1 || i > S->len)
{
puts("\n洗掉元素結點位置不合法!");
return 0;
}
(S->LAAP)[i - 1]->next = (S->LAAP)[i]->next;
free((S->LAAP)[i]);
(S->len)--;
for(int k = i;k + 1 < S->Alen;k++)
{
(S->LAAP)[k] = (S->LAAP)[k+1];
}
(S->Alen)--;
S->LAAP = (Lnode**)realloc(S->LAAP,sizeof(Lnode*)*(S->Alen));
if(S->LAAP == NULL)
{
puts("\n已經成功洗掉!但索引指標陣列多出一個空間,重新分配失敗!");
return 1;
}
puts("\n已經成功洗掉,并正確調整索引指標陣列!");
return 1;
}
int Traverse_SLinkList(SLinkList* S)
{
if((S->H) == NULL)
{
return -1;
}
if((S->H)->next == NULL)
{
puts("\n通過鏈表形態遍歷:");
printf("[H,len = 0]:頭結點->NULL\n");
return 1;
}
Lnode* p = (S->H)->next;
int flag = 0;
while(p != NULL)
{
if(flag == 0)
{
puts("\n通過鏈表形態遍歷:");
printf("[H,len = %d]:頭結點->%d",S->len,p->data);
flag = 1;
}
else
{
printf("->%d",p->data);
}
p = p->next;
}
printf("->NULL\n");
return 1;
}
int Traverse_ArraySLinkList(SLinkList* S)
{
for(int i = 0;i < S->Alen;i++)
{
if(i == 0)
{
puts("\n通過陣列形態遍歷:");
printf("[H,len = %d]:頭結點",S->len);
continue;
}
printf("->%d",(S->LAAP)[i]->data);
}
printf("->NULL\n");
return 1;
}
int Search_ArraySLinkList(SLinkList* S,int e)
{
for(int i = 1;i < S->Alen;i++)
{
if( (S->LAAP)[i]->data == e )
{
return i;
}
}
return 0;
}
int Get_ArraySLinkList(SLinkList* S,int n)
{
if(n >= 1 && n <= S->Alen - 1)
{
return (S->LAAP)[n]->data;
}
puts("\n獲取位置不合法!");
return -2147483648;
}
int Close_ArraySLinkList(SLinkList* S)
{
for(int i = 0;i < S->Alen;i++)
{
free((S->LAAP)[i]);
}
free(S->LAAP);
puts("關閉【數-鏈】結構成功!");
return 1;
}
int main()
{
SLinkList S;
init_ArraySLinkList(&S);
Traverse_SLinkList(&S);
Traverse_ArraySLinkList(&S);
puts("---------------------------------------------------");
Tail_ArraySLinkList(&S);
Traverse_SLinkList(&S);
Traverse_ArraySLinkList(&S);
puts("---------------------------------------------------");
fflush(stdin);
int n;
puts("輸入一個值可以查詢其在單鏈表中的位置(0-不存在):");
scanf("%d",&n);
printf("%d在第%d位置!\n",n,Search_ArraySLinkList(&S,n));
puts("---------------------------------------------------");
puts("輸入一個位置可以獲取該位置的值:");
scanf("%d",&n);
printf("第%d位置的值:%d\n",n,Get_ArraySLinkList(&S,n));
puts("---------------------------------------------------");
puts("輸入插入位置和值(空格分隔):");
int locate,value;
scanf("%d %d",&locate,&value);
Insert_ArraySLinkList(&S,locate,value);
Traverse_SLinkList(&S);
Traverse_ArraySLinkList(&S);
puts("---------------------------------------------------");
puts("輸入插入位置和值(空格分隔):");
scanf("%d %d",&locate,&value);
Insert_ArraySLinkList(&S,locate,value);
Traverse_SLinkList(&S);
Traverse_ArraySLinkList(&S);
puts("---------------------------------------------------");
int t;
puts("輸入要洗掉的位置:");
scanf("%d",&n);
Delete_ArraySLinkList(&S,n,&t);
Traverse_SLinkList(&S);
Traverse_ArraySLinkList(&S);
puts("---------------------------------------------------");
Close_ArraySLinkList(&S);
return 0;
}
二、 運行結果示例

------------------------------------------------------第十五次發專案類文章有點激動啊!-----------------------------------------------------
-----------------------------------------------------【C語言—微專案—自編練習】----------------------------------------------------------
----------------------------------------------------------------【TDTX】--------------------------------------------------------------------------
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/402731.html
標籤:其他
