/*
作用:單鏈表的實現(C語言)
日期:2015年4月
*/
// List.h
//結構體和函數的聲明
#ifndef LIST_H
#define LIST_H
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <iostream>
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node, *PNode;
typedef struct List
{
PNode head;
PNode tail;
int size;
}List,*PList;
bool InitList(PList list); // 初始化鏈表對象
void Create_t(PList list,ElemType x); // 尾插
void Create_h(PList list,ElemType x); // 頭插
void del_back(PList list); // 尾刪
void del_front(PList list); // 頭刪
void sortList(PList list); // 排序
void insert_val(PList list,ElemType x); // 按值插
PNode find(PList list,ElemType x); // 查找元素x的前面一個節點
void del_val(PList list,ElemType x); // 刪除值爲x的節點
void modify(PList list,ElemType x1,ElemType x2); // 修改節點的值
void clear(PList list); // 清空鏈表
void destroy(PList list); // 摧毀鏈表
void reserve(PList list); // 逆置鏈表
int length(PList list); // 求表長
void menu(); // 提示信息的顯示
void showList(PList list); // 顯示鏈表的內容
void show_tail(PList list); // 顯示尾節點的值(用於測試尾指針是否正確改變)
ElemType next(PList list,ElemType x); // 顯示值爲x的下一個節點
ElemType prio(PList list,ElemType x); // 顯示值爲x的前一個節點
PNode prev(PList list,PNode p); // 返回p指向節點的前面一個節點
#endif
// List.cpp
//結構體和函數的實現#include"List.h"
void menu() //提供選項的菜單函數
{
printf("*******************************************************************\n");
printf("* [0] quit_system [1] Create_t [2] Create_h [3] showList *\n");
printf("* [4] del_back [5] del_front [6] insert_val [7] show_tail *\n");
printf("* [8] find [9] del_val [10] sortList [11] modify *\n");
printf("* [12]clear [13] sort [14]destroy [15] resver *\n");
printf("* [16]length [17] next [18]prio *\n");
printf("********************************************************************\n");
}
bool InitList(PList list)
{
list->head = (PNode)malloc(sizeof(Node)); //初始化一個頭結點
assert(list->head != NULL); //斷言,表達式爲真,接着往下執行
list->head->next = NULL; //初始化head和tail指針,使其都指向頭節點
list->tail = list->head;
list->size = 0; //長度初始化爲0
return true;
}
void Create_t(PList list,ElemType x) //尾插法
{
PNode s = (PNode)malloc(sizeof(Node));
assert(s != NULL);
s->data = x; //填充數據域
s->next = NULL;
list->tail->next = s; //tail指向最後一個節點,把新建立的節點掛到鏈表的最後
list->tail = s; //改變尾指針的指向
list->size++;
}
void Create_h(PList list,ElemType x) //頭插法
{
PNode s = (PNode)malloc(sizeof(Node));
assert(s != NULL);
s->data = x; //填充數據域
s->next = list->head->next; //新節點指向第一個節點
list->head->next = s; //頭節點的next指向新節點s
if(list->size == 0) //如果是第一次頭插,需改變尾指針指向,之後都不改變
list->tail = s;
list->size++; //插入一個,長度加1
}
void del_back(PList list) //尾刪
{
if(0==list->size)
return;
PNode p = list->head;
while(NULL != p->next->next) //找到倒數第二個節點
{
p = p->next;
}
p->next = NULL; //把最後一個節點分離
free(list->tail); //釋放最後一個節點
list->tail = p; //尾指針指向原來的倒數第二個節點(現在倒數第一)
printf("尾節點已刪除\n");
list->size--;
}
void del_front(PList list) //頭刪
{
if(0==list->size)
return;
if(1==list->size) //只有一個節點,若刪去,需改變尾指針
list->tail = list->head;
PNode p = list->head->next; // p指向第一個節點
list->head->next = p->next; //頭指針指向第二個節點
free(p); //釋放第一個節點
printf("頭節點已刪除\n");
list->size--;
}
void showList(PList list) //鏈表顯示函數
{
if(1>list->size)
{
printf("鏈表爲空\n");
return ;
}
PNode p = list->head->next;
while(NULL!=p) //逐個遍歷鏈表
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
void show_tail(PList list) //爲測試尾指針是否正確改變,需顯示最後一個節點
{
printf("鏈表的尾節點是:》%d \n",list->tail->data);
}
void sortList(PList list) // 對無序鏈表進行從小到大排序
{
if(2>list->size)
return ;
PNode p = list->head->next;
PNode q = p->next;
for(int i = 0;i<list->size-1;i++,p = list->head->next,q = p->next) //n個數比較n-1趟
{
for(int j = 0;j<list->size-1-i;j++,p=q,q=q->next) //第i趟比較n-i次
{
if(p->data > q->data) //如果前面的數大於後面,則交換
{
p->data = p->data + q->data;
q->data = p->data - q->data;
p->data = p->data - q->data;
}
}
}
}
void insert_val(PList list,ElemType x) //鏈表有序的前提下,給一個值插入
{
PNode p = list->head->next,q = list->head;
while(NULL!=p) //找到能插入的位置,會在p、q之間
{
if(x<p->data)
break;
q = p;
p = p->next;
}
PNode s = (PNode)malloc(sizeof(Node)); //初始化新節點
s->data = x;
q->next = s; //把新節點插入到鏈表中
s->next = p;
if(NULL == p) //如果新節點的值最大,即尾插,需改變尾指針
list->tail = s;
list->size++;
}
PNode find(PList list,ElemType x) //返回要查找元素的前面一個的地址
{
PNode p = list->head;
while(NULL != p && NULL != p->next && x != p->next->data)
{
p = p->next; //循環結束,p指向x的前面一個元素
}
if(NULL==p->next) //如果p指向最後一個元素,說明沒有找到
{
printf("沒找到!\n");
return NULL;
}
return p;
}
void del_val(PList list,ElemType x) //刪除指定的值x
{
if(0 == list->size)
return ;
PNode p = find(list,x);
PNode q = NULL;
if(NULL == p)
{
printf("沒找到%d\n",x);
return ;
}
else
{
q = p->next; //q指向要刪除的節點
if(q == list->tail) //若刪除最後一個節點,需改變尾指針
{
p->next = NULL;
list->tail = p;
}
else
{
p->next = q->next;
}
free(q); //釋放要刪除的節點
list->size--;
}
return ;
}
void modify(PList list,ElemType x1,ElemType x2) //把原有的x1修改成x2
{
PNode p = find(list,x1);
if(NULL!=p)
p->next->data = x2;
else
printf("沒找到\n");
}
void clear(PList list) //刪除鏈表的所有節點,但不刪除頭結點
{
PNode p = list->head->next;
PNode q = p;
while(NULL!=p) //依次釋放節點
{
p = p->next;
free(q);
q = p;
}
list->tail = list->head; //修改尾指針和鏈表長度
list->size = 0;
}
void destroy(PList list) //摧毀鏈表,包括所有節點和頭結點
{
clear(list);
free(list->head);
list->head = NULL;
list->tail = NULL;
}
PNode prev(PList list,PNode p) //返回p指向的前面一個節點
{
if(p==list->head)
return NULL;
PNode q = list->head->next;
while(q!=NULL && q->next != p) //依次往後移,知道尾指針的前面一個節點
q=q->next;
return q;
}
void reserve(PList list) //逆置鏈表
{
PNode s = (PNode)malloc(sizeof(Node)); //建立一個節點
s->next = list->tail;
PNode p = list->tail;
while(list->tail != list->head->next) //把原鏈表的尾節點到第一個節點依次連接到新節點上
{
list->tail = prev(list,list->tail);
p->next = list->tail;
p=p->next;
}
p->next = NULL; //p指向第一個節點,即新鏈表的最後一個節點,尾指針的next域賦空,鏈表結束
free(list->head); //釋放原來的頭結點
list->head = s; //把s變成新的頭指針
}
int length(PList list) //求鏈表的長度
{
return list->size;
}
ElemType next(PList list,ElemType x) //返回x的後繼
{
PNode p = find(list,x);
if(p->next == list->tail)
{
printf("%d 沒有後繼!\n",x);
return -1;
}
if(p == list->tail)
{
printf("沒有找到%d\n",x);
return -1;
}
p=p->next;
return p->next->data;
}
ElemType prio(PList list,ElemType x) //返回x的前驅
{
PNode p = find(list,x);
if(p == list->head)
{
printf("%d 沒有前驅!\n",x);
return -1;
}
if(p == list->tail)
{
printf("沒有找到%d\n",x);
return -1;
}
return p->data;
}
//main.cpp
//測試鏈表以及函數實現
#include "List.h"
int main()
{
List mylist;
InitList(&mylist);
ElemType item = 0;
int pos = 0;
int chose = 1;
PNode p = NULL;
while(chose)
{
menu();
printf("給出想要操作的序號:\n");
scanf("%d",&chose);
switch(chose)
{
case 0:
destroy(&mylist);
chose = 0;
break;
case 1:
printf("輸入要尾插的數據[-1結束]:\n");
while(scanf("%d",&item),item!=-1)
{
Create_t(&mylist,item);
}
break;
case 2:
printf("輸入要頭插的數據:\n");
while(scanf("%d",&item),item!=-1)
{
Create_h(&mylist,item);
}
break;
case 3:
showList(&mylist);
break;
case 4:
del_back(&mylist);
break;
case 5:
del_front(&mylist);
break;
case 6:
printf("給出要插入的數:\n");
scanf("%d",&item);
insert_val(&mylist,item);
break;
case 7:
show_tail(&mylist);
break;
case 8:
printf("輸入要查找的數:\n");
scanf("%d",&item);
p = find(&mylist,item);
if(NULL!=p)
printf("%d\n",p->next->data);
break;
case 9:
printf("輸入要刪除的數:\n");
scanf("%d",&item);
del_val(&mylist,item);
break;
case 10:
sortList(&mylist);
break;
case 11:
printf("輸入要修改的數和修改後的數\n");
scanf("%d %d",&item,&pos);
modify(&mylist,item,pos);
break;
case 12:
clear(&mylist);
break;
case 13:
sortList(&mylist);
break;
case 14:
destroy(&mylist);
break;
case 15:
reserve(&mylist);
break;
case 16:
printf("鏈表長度爲:%d\n",length(&mylist));
break;
case 17:
printf("輸入想要找哪個一數的後繼:\n");
scanf("%d",&item);
printf("%d 的後繼是:%d\n",item,next(&mylist,item));
break;
case 18:
printf("輸入想要找哪個一數的前驅:\n");
scanf("%d",&item);
printf("%d 的前驅是:%d\n",item,prio(&mylist,item));
break;
default:
printf("重新輸入\n");
break;
}
}
return 0;
}
<img src="https://img-blog.csdn.net/20150508194624040?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ2hlbmd6aV9jb21t/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<img src="https://img-blog.csdn.net/20150508194639484?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ2hlbmd6aV9jb21t/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />