數據結構線性表鏈表的C語言實現
說明:線性表是一種最簡單的線性結構,也是最基本的一種線性結構,所以它不僅是學習中的重點,也是應用開發非常常用的一種數據結構。它可以分為順序表和鏈表。它的主要操作是數據元素的插入,刪除,以及排序等。接下來,本篇文章將對線性表鏈表的基本操作和運用進行詳細的說明(包含在源代碼的注釋中),並給予可運行的程序源代碼。
線性表鏈表不同於順序表,它是一種鏈式的線性表,和順序表的類似數組的存儲特點不同,它是一個個獨立的存儲單元,中間用指針鏈接,類似一條鏈子,所以叫鏈表。因為同屬線性表所以它的基本操作與順序表是一致的,所以基本操作函數名相同但是具體實現方式不同,順序表的優點在於它可以隨機存儲數據元素,但在刪除和插入操作時需要移動大量元素。而鏈表則相反,它無法做到隨機存取,但在進行刪除和插入操作時非常方便,僅需要修改下指針並釋放被刪除元素的存儲空間而已。
程序分析:由於抱着是程序執行起來時操作盡量簡單化,使人一看就能明白,所以本程序是用了不少的提示性語句。主函數的結構是while循環和switch函數相結合的方法,使每種能夠用到的基本操作盡量明白的顯示在主顯示函數中,這樣能使每種基本操作的作用效果更加突出明了。這樣不僅能使程序的模塊化盡量明顯,也可以讓源代碼的可讀性增強。而且程序運用了CLS清屏函數,可以使每一次操作的輸入輸出結果更加清晰。
源代碼:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define OK 1
#define ERROW -1
#define OVERFLOW -2
#define LEN sizeof(struct Lnode)
#define LN LNode *
typedef int Status;
typedef int ElemType;
/*鏈表的結點的數據結構 */
typedef struct Lnode
{
ElemType num; //為求簡便數據域僅置一項
struct Lnode *next;
}LNode,*LinkList; // *LinkList L 定義鏈表頭指針
/*鏈表的初始構建函數*/
Status InitList(LinkList &L)
{
L=(LN)malloc(LEN);
if(L==0)
exit(OVERFLOW);
L->next=NULL;
return OK;
}
/*鏈表的清空涵數*/
void ClearList(LinkList &L)
{
LinkList p;
while(L->next)
{
p=L->next;
L->next=p->next;
free(p);
}
// 最終效果是只保留頭節點
}
/*銷毀函數*/
void DestoryList(LinkList &L)
{
ClearList(L);
free(L); //釋放頭節點空間
L=NULL;//鏈表的變量歸於初始值,便於識別和處理
}
/*取表長函數*/
Status GetLength(LinkList L)
{
int n;
n=0;
if(L==NULL)//未經初始構建函數構建或已經徹底銷毀
return n;
while(L->next)
{
L=L->next;
n++;
}
return n;
}
/*判斷表的空否的函數 */
Status IsEmpty(LinkList L)
{
if(L->next==NULL)
return OK;
else
return ERROW;
}
/*定位取值函數*/
Status GetElem(LinkList L,int i,ElemType &e)
{
int j=1;
LinkList p;
p=L->next;
while(p&&j<i)
{
p=p->next;
j++;
}
if(p==NULL||j>i) //所給位置序號超出表長
{
printf("序號輸入錯誤!\n\n");
return ERROW;
}
e=p->num;
return OK;
}
/*查找定位函數*/
Status LocateElem(LinkList L,int &i,ElemType e)
{
i=1;
LinkList p;
p=L->next;
while(p&&p->num!=e)
{
p=p->next;
i++;
}
if(p!=NULL)
return OK;
else
return ERROW;
}
/*創建一個鏈表*/
void ScanList(LinkList &L)
{
int i;
LinkList p,p0;
if(L==NULL)
InitList(L);
p0=L;
printf("請輸入鏈表長度\n");
scanf("%d",&i);
printf("\n請輸入%d個數\n",i);
for(;i>0;i--)
{
p=(LN)malloc(LEN);
p->next=NULL;
scanf("%d",&p->num);
p0->next=p;
p0=p;
}
}
/*輸出表中所有數據元素*/
void PrintList(LinkList L)
{
LinkList p0;
p0=L->next;
printf("\n");
while(p0!=NULL)
{
printf("%d ",p0->num);
p0=p0->next;
}
printf("\n");
}
/*數據元素插入函數*/
Status ListInsert(LinkList &L,int i,ElemType e)
{
int j=0;
LinkList p,p0;
p=L;
while(p&&j<i-1)
{
p=p->next;
j++;
}
if(p==NULL||j>i)
{
return ERROW;
}
p0=(LN)malloc(LEN);
p0->num=e;
p0->next=p->next;
p->next=p0;
return OK;
}
/*定位刪除函數*/
Status ListDelete_1(LinkList &L,int i)
{
int j=0;
LinkList p,p0;
p=L;
while(p&&j<i-1)
{
p=p->next;
j++;
}
if(p==NULL||j>i)
{
return ERROW;
}
p0=p->next;
p->next=p0->next;
free(p0);
return OK;
}
/*非遞減冒泡排序函數*/
int maopao(LinkList &L)
{
int i,j,t,n;
LinkList p,p0;
p0=L;
n=GetLength(L);
for(j=1;j<=n-1;j++)
{
p0=p0->next;
p=p0;
for(i=1;i<=n-j;i++)
{
if(p->num>p->next->num)
{
t=p->num;
p->num=p->next->num;
p->next->num=t;
}
p=p->next;
}
}
return OK;
}
/*主提示函數*/
void printlin()
{
printf("\n");
printf("\t\t\t線性鏈表基本操作學習系統\n");
printf("\t\t\t ***主菜單***\n\n");
printf("\t\t\t *1 創建一個鏈表表\n");
printf("\t\t\t *2 定位輸出一個數據元素\n");
printf("\t\t\t *3 輸出鏈表中所有元素\n");
printf("\t\t\t *4 定位插入一個數據元素\n");
printf("\t\t\t *5 定位刪除一個數據元素\n");
printf("\t\t\t *6 定值刪除一個數據元素\n");
printf("\t\t\t *7 清空鏈表\n");
printf("\t\t\t *8 銷毀鏈表\n");
printf("\t\t\t *9 對表內數據元素進行非遞減排序\n");
printf("\t\t\t *0 結束程序\n");
}
int main()
{
int i,j,k;
LinkList L;
L=NULL;
printf("編寫此程序目的是自我學習線性表鏈表\n");
printlin();
while(1)
{
int t;
scanf("%d",&t);
if(t!=0)
if(t==1||GetLength(L)!=0)
{
switch(t)
{
case 1: if(GetLength(L)!=0)
{
printf("鏈表已存在,是銷毀並重新創建鏈表?\n");
printf("*1 是 *2 否\n");
scanf("%d",&i);
if(i==1)
{
DestoryList(L);
ScanList(L);
}
}
else
ScanList(L);
break;
case 2: {
k=GetLength(L);
printf("請輸入數據位置\n");
scanf("%d",&i);
if(i<1||i>k)
printf("輸入位置錯誤\n");
else
{
GetElem(L,i,j);
printf("第%d個數為%d\n",i,j);
}
break;
}
case 3: PrintList(L);break;
case 4: {
printf("輸入要插入的位置\n");
scanf("%d",&i);
printf("請輸入要插入的數據\n");
scanf("%d",&j);
k=ListInsert(L,i,j);
if(k==-1)
printf("插入位置不合法,插入數據操作失敗!\n\n");
else
printf("插入數據成功\n\n");
break;
}
case 5: {
printf("請輸入要刪除數據位置\n");
scanf("%d",&i);
k=ListDelete_1(L,i);
if(k==-1)
printf("輸入位置錯誤,刪除操作失敗!\n\n");
else
printf("刪除成功!\n\n");
break;
}
case 6: {
printf("請輸入需要刪除的元素:\n");
scanf("%d",&j);
k=LocateElem(L,i,j);
if(k==-1)
printf("未找到該元素,刪除操作失敗!\n\n");
else
{
ListDelete_1(L,i);
printf("刪除成功!\n\n");
}
break;
}
case 7: {
ClearList(L);
printf("清空完畢,返回主菜單\n\n");
break;
}
case 8: {
DestoryList(L);
printf("銷毀成功,返回主菜單\n\n");
break;
}
case 9: {
maopao(L);
printf("已成功排序,返回主菜單\n\n");
break;
}
case 0: break;
default: {
printf("輸入有誤,可以重新選擇,退出按0!\n\n");
}
}
}
else
printf("鏈表未創建或已清空或銷毀,請先創建鏈表\n\n");
system("pause");
system("CLS");
printlin();
if(t==0)
break;
}
return 0;
}
程序運行效果圖 (部分):

圖 1

圖2

圖3

圖4
結束語:紙上得來終覺淺,絕知此事要躬行!
