鏈式單鏈表
題目:
構造一個單鏈表,實現建立、刪除、插入、查詢等功能。
解析:
初始化單鏈表,即單鏈表的表頭指標為空
void initlist(node **pnode)
{
*pnode = NULL;
printf("初始化成功!\n");
}
列印連結串列元素,遍歷連結串列
//列印連結串列元素,遍歷連結串列 void printinfo(linklist list) { lnode *head; if(head == NULL)//連結串列為空 cout<<"連結串列為空!"<<endl; //連結串列不為空則輸出打印出元素 else { cout<<"連結串列元素為:"; for(head=list;head!=NULL;head=head->next)//第一個指向list cout<<head->data<<" "; cout<<endl<<endl; } }
知曉連結串列長度建立一個線性連結串列
從線性表的第一個元素開始依次獲取表中的資料元素,每取得一個數據元素,就為該資料元素生成一個新的鏈結點,將取得的資料元素的資料資訊送新的結點的資料域的同時,將新結點的指標域置為NULL,然後將新的鏈結點插入到連結串列的尾部。當取第1個數據元素時,連結串列為空,此時只需要將新的鏈結點的地址傳送即可 。
linklist creat(int n) { linklist p,r,next = NULL; elemtype a; for(int i=1;i<=n;i++) { scanf("%d",&a);//獲取一個數據元素 p = (linklist)malloc(sizeof(node));//申請一個新的結點 p->data = a; p->next = NULL;//連結串列末尾指標域置空 if(next == NULL) next = p; else r->next = p;//將新的結點連結在連結串列的尾部 r=p;//指標變數總是指向連結串列的末尾 } return next; }
求連結串列的長度(1)
首先將指標指向連結串列的第一個鏈結點,然後遍歷連結串列,指標變數每指向一個鏈結點,計數器就加1,遍歷結束後,計數器的資料就是連結串列的長度。
int length1(linklist list)
{
linklist p = list;
int n = 0;
while(p!=NULL)
{
n++;//計數器累加
p = p->next; //指標p指向下一個鏈結點
}
return n;//返回連結串列的長度
}
求連結串列的長度(2)
遞迴結構,即每個鏈結點的指標域均指向一個線性連結串列,它所指向的鏈結點為該連結串列的第1個鏈結點。
int length2(linklist list)
{
if(list!=NULL)
return 1+length2(list->next);
else
return 0;
}
測試連結串列是否為空
如果指標指向的第1個鏈結點為NULL,則連結串列為空,否則連結串列非空。
void isempty(linklist list)
{
if(list == NULL)
printf("連結串列為空\n");
else
printf("連結串列非空\n");
}
確定元素item線上性連結串列中的位置
從連結串列的第1個鏈結點開始,依次遍歷連結串列,查詢其是否與給定值item相匹配。如果相匹配則輸出item的位置,否則則輸出連結串列中該值不存在。
linklist find(linklist list,elemtype item)
{
linklist p = list;
int place = 1;//計數器記錄位置
while(p !=NULL && p->data != item)//查詢是否匹配
{
place++;
p = p->next;
}
if(p !=NULL && p->data == item)
cout<<"item的位置為:"<<place<<endl;
else
cout<<"item不存在!"<<endl;
}
在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點
首先申請一個新的鏈結點,將其資料資訊item置於新鏈結點的資料域內,然後將第1個結點的指標list送入新結點的指標域內,同時將新結點的地址賦予給list,從而新結點插入連結串列的最前面,由此完成插入。
void insert1(linklist &list,elemtype item)
{
//list中存放連結串列的首地址
linklist p;
p = (linklist)malloc(sizeof(node));//申請一個新的連結點
p ->data = item;//將item送新結點的資料域
p ->next = list;//將list送新結點的指標域
list = p;//list指向新結點
}
非空線性連結串列的末尾插入一個數據信息為item的連結點
首先設定一個指標變數,使其指向連結串列的第1個鏈結點,然後反覆執行直到其等於NULL,此時指標指向連結串列的末尾鏈結點,然後將item送入申請的新結點的資料域的同時,將新的結點的指標域置為NULL,最後將新的結點的地址送入指標變數指向的鏈結點的指標域中,由此完成插入。
void insert2(linklist list,elemtype item)
{
//list存放連結串列的首地址
linklist p,r;
r = list;
while(r->next!=NULL)
r = r->next;//找到連結串列末尾結點的地址
p = (linklist)malloc(sizeof(node));//申請一個新的連結點
p ->data = item;//將item送新結點的資料域
p ->next = NULL;//新結點的指標域置為NULL
r ->next =p;//插入連結串列的末尾
}
線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點
從第1個結點開始查詢直到第i個結點,然後將新的結點插到它們的後面。如果不存在第i個鏈結點則輸出不存在。如果存在第i個鏈結點則申請一個新的結點,然後將item送入新的結點的資料域,並且將新的結點插到第i個鏈結點之後,如此插入成功。
void insert4(linklist list,int i,elemtype item)
{
linklist p,q = list;
int j=1;
while(j<i&&q!=NULL)
{
q = q ->next;
j++;
}//尋找第i個鏈結點
if(j!=i||q==NULL)
printf("連結串列中不存在第i個鏈結點");
p = (linklist)malloc(sizeof(node));//申請一個新的鏈結點
p ->data = item;//將item送新結點的資料域
p ->next = q ->next;
q ->next = p;//將新結點插入第i個鏈結點之後
}
在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點
先為被插入的鏈結點申請一個新的鏈結點,然後從連結串列的第一個鏈結點開始順序查詢插入位置,在查詢的過程中保留當前鏈結點的直接前驅結點的位置,由此進行插入。
void insert5(linklist &list,elemtype item)
{
linklist p,q,r;
p = (linklist)malloc(sizeof(node));
p ->data = item;
if(list==NULL||item<list->data)//若連結串列為空或者item小於第1個鏈結點
{
p ->next = list;//將新的鏈結點插在連結串列最前面
list = p;//list指向被插入的新結點
}
else
{
q = list;
while(q!=NULL&&item>=q->data)//尋找插入位置
{
r = q;
q = q->next;
}
p->next = q;
r->next = p;//將新的鏈結點插在q指示的鏈結點後面
}
}
銷燬一個線性連結串列
設定一個指標變數,先將其指向連結串列的第1個鏈結點,然後遍歷整個連結串列,過程中刪除並釋放鏈結點。
void deletelist(linklist &list)
{
linklist p = list;
while(p!=NULL)
{
list = p->next;//儲存下一個鏈結點的位置
free(p);//刪除並釋放當前的鏈結點
p = list;//下一個鏈結點成為當前鏈結點
}
}
刪除第k個結點
從連結串列第一個鏈結點開始,找到第k個鏈結點,然後刪除該結點並釋放空間。
lnode* getelem(linklist list,int k)
{
lnode* s=list;
while(k)
{
s=s->next;
k--;
}
return s;
}
void deletelist3(linklist list,int k)
{
lnode* p=list;
lnode* q=NULL;
p=getelem(list,k-1);
q=p->next;
p->next=q->next;
free(q);
}
逆轉一個線性連結串列
通過改變鏈結點指標域中的地址來依次改變資料元素的關係。
//逆轉一個線性連結串列
void invert(linklist &list)
{
linklist p,q,r;
p = list;
q = NULL;
while(p!=NULL)
{
r = q;
q = p;
p = p->next;
q->next = r;
}
list = q;
}
複製一個線性連結串列
如果一個連結串列為空,則輸出連結串列為空。如果連結串列非空則複製連結串列所指的鏈結點,並將該鏈結點的指標賦給另外一個鏈結點,然後複製鏈結點後面一個鏈結點,最後返回另一個連結串列的第1個鏈結點
//複製一個線性連結串列
linklist copy(linklist lista)
{
linklist listb;
if(lista==NULL)
cout<<"連結串列為空"<<endl;
else
{
listb = (linklist)malloc(sizeof(node));
listb->data = lista->data;
listb->next = copy(lista->next);
}
return listb;
}
附:原始碼
#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;
typedef int elemtype;
typedef struct node
{
elemtype data;//資料域
struct node *next;//指標域
}lnode,*linklist;//定義一個線性連結串列的型別
void initlist(linklist *pnode)
{
*pnode = (linklist)malloc(sizeof(lnode));
if(*pnode == NULL)
printf("初始化失敗\n\n");
else
{
(*pnode)->next =NULL;
printf("初始化成功!\n\n");
}
}
linklist creat(int n)
{
linklist p,r,next = NULL;
elemtype a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);//獲取一個數據元素
p = (linklist)malloc(sizeof(node));//申請一個新的結點
p->data = a;
p->next = NULL;//連結串列末尾指標域置空
if(next == NULL)
next = p;
else
r->next = p;//將新的結點連結在連結串列的尾部
r=p;//指標變數總是指向連結串列的末尾
}
return next;
}
//求線性連結串列的長度
int length1(linklist list)
{
linklist p = list;
int n = 0;
while(p!=NULL)
{
n++;//計數器累加
p = p->next; //指標p指向下一個鏈結點
}
return n;//返回連結串列的長度
}
//求線性連結串列的長度(遞迴)
int length2(linklist list)
{
if(list!=NULL)
return 1+length2(list->next);
else
return 0;
}
//測試線性連結串列是否為空
void isempty(linklist list)
{
if(list == NULL)
printf("連結串列為空\n");
else
printf("連結串列非空\n");
}
//確定元素item線上性連結串列中的位置
linklist find(linklist list,elemtype item)
{
linklist p = list;
int place = 1;
while(p !=NULL && p->data != item)
{
place++;
p = p->next;
}
if(p !=NULL && p->data == item)
cout<<"item的位置為:"<<place<<endl;
else
cout<<"item不存在!"<<endl;
}
//在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點
void insert1(linklist &list,elemtype item)
{
//list中存放連結串列的首地址
linklist p;
p = (linklist)malloc(sizeof(node));//申請一個新的連結點
p ->data = item;//將item送新結點的資料域
p ->next = list;//將list送新結點的指標域
list = p;//list指向新結點
}
//非空線性連結串列的末尾插入一個數據信息為item的連結點
void insert2(linklist list,elemtype item)
{
//list存放連結串列的首地址
linklist p,r;
r = list;
while(r->next!=NULL)
r = r->next;//找到連結串列末尾結點的地址
p = (linklist)malloc(sizeof(node));//申請一個新的連結點
p ->data = item;//將item送新結點的資料域
p ->next = NULL;//新結點的指標域置為NULL
r ->next =p;//插入連結串列的末尾
}
//線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點
void insert4(linklist list,int i,elemtype item)
{
linklist p,q = list;
int j=1;
while(j<i&&q!=NULL)
{
q = q ->next;
j++;
}//尋找第i個鏈結點
if(j!=i||q==NULL)
printf("連結串列中不存在第i個鏈結點");
p = (linklist)malloc(sizeof(node));//申請一個新的鏈結點
p ->data = item;//將item送新結點的資料域
p ->next = q ->next;
q ->next = p;//將新結點插入第i個鏈結點之後
}
//在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點
linklist insert5(linklist &list,elemtype item)
{
linklist p,q,r;
p = (linklist)malloc(sizeof(node));
p ->data = item;
if(list==NULL||item<list->data)//若連結串列為空或者item小於第1個鏈結點
{
p ->next = list;//將新的鏈結點插在連結串列最前面
list = p;//list指向被插入的新結點
}
else
{
q = list;
while(q!=NULL&&item>=q->data)//尋找插入位置
{
r = q;
q = q->next;
}
p->next = q;
r->next = p;//將新的鏈結點插在q指示的鏈結點後面
}
return list;
}
//銷燬一個線性連結串列
void deletelist(linklist &list)
{
linklist p = list;
while(p!=NULL)
{
list = p->next;//儲存下一個鏈結點的位置
free(p);//刪除並釋放當前的鏈結點
p = list;//下一個鏈結點成為當前鏈結點
}
}
lnode* getelem(linklist list,int k)
{
lnode* s=list;
while(k)
{
s=s->next;
k--;
}
return s;
}
void deletelist3(linklist list,int k)
{
lnode* p=list;
lnode* q=NULL;
p=getelem(list,k-1);
q=p->next;
p->next=q->next;
free(q);
}
//逆轉一個線性連結串列
void invert(linklist &list)
{
linklist p,q,r;
p = list;
q = NULL;
while(p!=NULL)
{
r = q;
q = p;
p = p->next;
q->next = r;
}
list = q;
}
//複製一個線性連結串列
linklist copy(linklist lista)
{
linklist listb;
if(lista==NULL)
cout<<"連結串列為空"<<endl;
else
{
listb = (linklist)malloc(sizeof(node));
listb->data = lista->data;
listb->next = copy(lista->next);
}
return listb;
}
//列印連結串列元素,遍歷連結串列
void printinfo(linklist list)
{
lnode *head;
if(head == NULL)//連結串列為空
cout<<"連結串列為空!"<<endl;
//連結串列不為空則輸出打印出元素
else
{
cout<<"連結串列元素為:";
for(head=list;head!=NULL;head=head->next)//第一個元素指向list
cout<<head->data<<" ";
cout<<endl<<endl;
}
}
int main()
{
lnode *list = NULL;
elemtype length = 0,item;
//測試連結串列是否為空
cout<<"測試連結串列是否為空!"<<endl;
isempty(list);
//初始化單鏈表,即單鏈表的表頭指標為空
cout<<endl<<"初始化連結串列!"<<endl;
initlist(&list);//連結串列初始化
//知曉連結串列長度建立一個線性連結串列
cout<<"建立連結串列!"<<endl;
int m;//長度
cout<<"輸入連結串列長度:";
scanf("%d",&m);
cout<<"輸入資料:";
list = creat(m);//資料元素需要接收回來賦給list
printinfo(list);
//求線性連結串列的長度
cout<<"連結串列的長度:";
cout<<length1(list)<<endl;
//遞迴求連結串列的長度
cout<<"遞迴求連結串列的長度:";
cout<<length2(list)<<endl<<endl;
//測試連結串列是否為空
cout<<"測試連結串列是否為空!"<<endl;
isempty(list);
//確定元素item線上性連結串列中的位置
cout<<endl<<"確定item在連結串列中的位置!"<<endl;
cout<<"輸入item:";
scanf("%d",&item);
find(list,item);
//在非空線性連結串列的第1個鏈結點前插入一個數據信息為item的鏈結點
cout<<endl<<"在連結串列第1個鏈結點插入item!"<<endl;
cout<<"輸入item:";
scanf("%d",&item);
insert1(list,item);
printinfo(list);
//非空線性連結串列的末尾插入一個數據信息為item的連結點
cout<<endl<<"在連結串列末尾插入item!"<<endl;
cout<<"輸入item:";
scanf("%d",&item);
insert2(list,item);
printinfo(list);
//線上性連結串列中的第i個鏈結點後面插入一個數據信息為item的連結點
cout<<endl<<"在連結串列中的第i個鏈結點後面插入item!"<<endl;
cout<<"輸入item:";
scanf("%d",&item);
elemtype i;
cout<<"輸入i:";
scanf("%d",&i);
insert4(list,i,item);
printinfo(list);
//在按值有序連結的線性連結串列中插入一個數據信息為item的鏈結點
cout<<endl<<"在按值有序連結的線性連結串列中插入item!"<<endl;
cout<<"輸入item:";
scanf("%d",&item);
list = insert5(list,item);
printinfo(list);
//刪除第 k 個節點
cout<<endl<<"刪除第k個結點!"<<endl;
elemtype k;
cout<<"輸入k:";
cin>>k;
deletelist3(list,k);
printinfo(list);
//逆轉一個線性連結串列
cout<<endl<<"逆轉連結串列!"<<endl;
invert(list);
printinfo(list);
//複製一個線性連結串列
cout<<"複製連結串列!"<<endl;
copy(list);
printinfo(list);
//銷燬一個線性連結串列
cout<<endl<<"銷燬連結串列!"<<endl;
deletelist(list);
isempty(list);
return 0;
}