目录
一、链表
基本概念 : 链表一种线性的数据结构,通过指针将一个个零散的内存块连接起来,链表的每个内存块称为结点。
二、单向链表
单向链表的数据块分为两部分,一部分是数据,一部分是指针,指针指向下一个节点,所以只能从前向后遍历
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct student_information
{
int num; //学号
char name[10]; //姓名
} student;
typedef struct chainlist
{
student data;
chainlist *next;
chainlist *pre;
}chainlist;
typedef struct headnode
{
int length;
chainlist *first;
}headnode;
headnode *Creat(headnode *list)
{// 构造一个空链表
list=new headnode;//产生一个仅有表头结点的链表
list->first=NULL;//first的值设为空(NULL)值
list->length=0;
return list;
}
bool insert(headnode *head,int k,student stu1)
{
if (k < 0||k>head->length)
return false;
int index=1;
chainlist *current=head->first;
while(index<k&¤t)
{
index++;
current=current->next;
}
chainlist *q=new chainlist;
q->data=stu1;
if(k>1)
{
q->next=current->next;//next存储current的next current的next指向原来下一个数据的地址 每一个节点有自己的地址,但也存储着下一个节点的地址
current->next=q;//current的next存储q的地址,相当于当前节点指向q
}
else
{
q->next=head->first;
head->first=q;
}
head->length++;
return true;
}
void Output(headnode *head)
{// 逐个地输出链表L中的数据元素
chainlist *current=head->first;
while (current)
{
if(current->data.num!=0)
cout<<current->data.num<<current->data.name<<" ";
current=current->next ;
}
cout<<endl;
}
int main(){
int i=0;
student stu1;
headnode *l;
l=Creat(l);
cout<<"请输入学生数据\n";
while(cin>>stu1.num)
{
if(stu1.num==0)
break;
else
{
cin>>stu1.name;
insert(l,i,stu1);
i++;
}
}
Output (l);
printf("共有学生%d人",i);
}
三、双向链表
在学习完了单向链表之后,对单向链表有了自己的理解。数据是通过指针指向链接的,一个数据块分为三部分,一个存储数据,一个pre指针,一个next指针
通过pre和next将数据串在一起
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct student_information
{
int num; //学号
char name[10]; //姓名
} student;
typedef struct chainlist
{
student data;
chainlist *next;
chainlist *pre;
}chainlist;
typedef struct headnode
{
int length;
chainlist *first;
}headnode;
headnode *Creat(headnode *head)
{// 构造一个空链表
head=new headnode;//产生一个仅有表头结点的链表
head->first=NULL;//first的值设为空(NULL)值
head->length=0;
return head;
}
bool insert(headnode *head,int k,student stu1)
{
if (k < 0||k>head->length)
return false;
int index=1;
chainlist *current=head->first;
while(index<k&¤t)
{
index++;
current=current->next;
}
chainlist *q=new chainlist;
q->data=stu1;
if(k>1)
{
q->next=current->next;
q->pre=current;
chainlist *p=current->next;
if(p)
p->pre=q;
current->next=q;
}
else
{
q->next=head->first;
q->pre=NULL;
chainlist *p=head->first;
if(p)
p->pre=q;
head->first=q;
}
head->length++;
return true;
}
void Output(headnode *head)
{// 逐个地输出链表L中的数据元素
chainlist *current=head->first;
while (current)
{
if(current->data.num!=0)
cout<<current->data.num<<current->data.name<<" ";
current=current->next ;
}
cout<<endl;
}
int main(){
int i=0;
student stu1;
headnode *l;
l=Creat(l);
cout<<"请输入学生数据\n";
while(cin>>stu1.num)
{
if(stu1.num==0)
break;
else
{
cin>>stu1.name;
insert(l,i,stu1);
i++;
}
}
Output (l);
printf("共有学生%d人",i);
}
四、学生管理系统
在构建双向链表的基础上,增加了遍历链表,查询数据,删除节点,增加节点等功能。
运用了模板类,不会的话可以去看看黑马程序员的C++教程。
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include<iomanip>
//#include"function.h"
//#include"choose_function.h"
using namespace std;
typedef struct student_information
{
char num[100]; //学号
char name[100]; //姓名
float score1 ;
float score2;
float score3;
float aver;
} student;
typedef struct chainlist
{
student data;
chainlist *next;
chainlist *pre;
}chainlist;
typedef struct headnode
{
int length;
chainlist *first;
}headnode;
typedef struct Data_elements_for_direct_and_direct_rear_drives
{
chainlist *prenode;
chainlist *nextnode;
} resultnode;//返回直接前驱和直接后驱的数据元素的地址结果
class doublechainlist
{
private :
headnode *head;
public :
headnode* doublechianlist();
bool insert(int k,student stu1);
void output();
bool deletenode(int k) ;
bool search_information(char *k,student &stu2);
bool input(doublechainlist list1,int &i,student stu1);
void printmenuname() ;
void printmenu();
bool choose_function(doublechainlist list1,student stu1,char j,int &n,student &stu2);
int lenth();
bool search_before_and_after(char *k,int j,int i,student &stu3,student &stu4);
void printsinglestudentinformation(student stu);
};
headnode* doublechainlist::doublechianlist()
{// 构造一个空链表
head=new headnode;//产生一个仅有表头结点的链表
head->first=NULL;//first的值设为空(NULL)值
head->length=0;
return head;
}
bool doublechainlist::search_before_and_after(char *k,int j,int i,student &stu3,student &stu4)
{
chainlist *current =head->first;
resultnode node1;
int a=0;
int b=0;
while(current)
{
if(strcmp(current->data.num,k)==0)
break;
current=current->next;
}
node1.prenode=current;
node1.nextnode=current;
cout<<current->data.num;
if(current)
{
while(a<j&&node1.prenode)
{
node1.prenode=node1.prenode->pre;
a++;
}
stu3=node1.prenode->data;
while(b<i&&node1.nextnode)
{
node1.nextnode=node1.nextnode->next;
b++;
}
stu4=node1.nextnode->data;
return true;
}
else
return false;
}
int doublechainlist::lenth()
{
chainlist *current = head->first;
int n =0;
while(current)
{
n++;
current = current->next;
}
return n;
}
bool doublechainlist::choose_function(doublechainlist list1,student stu1,char j,int &n,student &stu2)
//操作选择函数
{
int k,i,g;
char p[100];
int pos; //为什么pos不能定义为 unsigned
switch(j)
{
case '1' ://显示线性表中的数据元素
//system("cls");
output();
//system("pause");
//system("cls");
return true;
break;
case '2' ://初始化学生信息
cout<<"请输入学生数据,学号+空格+姓名+空格+成绩1+空格+成绩2+成绩3,以学号为零结束\n\t";
if(input(list1,n,stu1));
return true;
break;
case '3' ://插入数据元素
//system("cls");
n=lenth();
output();
cout<<"\n\t当前数据元素的下标范围:0---"<<n<<endl;
printf("\n\t请输入要插入点的下标:");
cin>>k;
if (k < 0||k>n )
{
cout <<"\n"<<"非法下标,请重新选择功能"<<endl;
return true;
break;
}
cout<<"请输入学生数据,学号+空格+姓名+空格+成绩1+空格+成绩2+成绩3,以学号为零结束\n\t";
cin>>stu1.num>>stu1.name>>stu1.score1>>stu1.score2>>stu1.score3;
if(insert(k,stu1))
{
printf("插入成功!\n\n");
cout<<"现在的学生表为:\n";
output();
}
else
printf("插入失败!\n\n");
//system("pause");
//system("cls");
return true;
break;
case '4'://删除数据元素
//system("cls");
//output(L);
n=lenth();
cout<<"\n\t当前数据元素的下标范围:1---"<<n<<endl;
printf("\n\t请输入要删除数据元素的下标:");
cin>>k;
if (k < 1 )
{
cout <<"\n"<<"请重新选择"<<endl;
//system("pause");
//system("cls");
return true;
break;
}
if(deletenode(k))
{
printf("删除成功!目前的学生表为:\n\n");
output();
}
else
printf("删除失败!\n\n");
//system("pause");
//system("cls");
return true;
break;
case '5'://查找数据元素
//system("cls");
cout<<"当前双向链表中的学生信息如下"<<endl;
output();
printf("\n\t请输入要查找的学生学号:");
cin>>p;
if(search_information(p,stu2))//返回x所在的数组位置下标
{
printf("查找成功!\n\n");
printsinglestudentinformation(stu2);
}
else
printf("\n查找失败!\n\n");
//system("pause");
//system("cls");
return true;
break;
case '6'://取序列第k个元素
output();
int j,i;
char num[100];
student stu3;
student stu4;
cout<<"查找某一学生的第n个前驱和第m个后继元素"<<endl;
printf("\n\t请输入学生学号:");
cin>>num;
printf("\n\t第几个前驱号:\n");
cin>>j;
printf("\n\t第几个后继:\n");
cin>>i;
if (j < 1||i < 1 )
{
return true;
break;
}
if(search_before_and_after(num,j,i,stu3,stu4))
{
printf("获取成功!\n\n");
cout<<num<<"的第"<<j<<"个前驱元素是:\n\t\t";
printsinglestudentinformation(stu3);
cout<<num<<"的第"<<i<<"个后继元素是:\n\t\t";
printsinglestudentinformation(stu4);
}
else
printf("\n取出失败!\n\n");
//system("pause");
//system("cls");
return true;
break;
case '0':
exit(0);
break;
default :
//cout <<"请重新选择"<<endl;
//system("pause");
//system("cls");
return false;
break;
}//end switch
}
void doublechainlist::printmenuname()
//我就是我
{
//system("color FA");
printf("\n\n\n\n\n\n\n");
//system("color EA");
printf(" *************************************************\n");
//system("color FA");
printf(" 学生成绩单的双向链表存储\n\n");
printf(" 制作: paul_chen21\n");
printf(" 班级:cpp\n");
printf(" 学号: 20222022\n");
printf(" 指导老师: @paul\n");
//system("color EA");
printf(" *************************************************\n");
//system("color FA");
printf("\n\n\n\t\t");
}
void doublechainlist::printsinglestudentinformation(student stu)
{
cout<<"\n\n";
cout<<" ┌────────────────────────────────────────────────────────────────┐"<<endl;
cout<<" │ 成 绩 单 │"<<endl;
cout<<" ├──────────┬──────┬──────────┬──────────┬──────────┬─────────────┤"<<endl;
cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" │ 学号 │姓 名 │ 成绩1 │ 成绩2 │ 成绩3 │ 平均成绩 │"<<endl;
cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" ├──────────┼──────┼──────────┼──────────┼──────────┼─────────────┤"<<endl;
stu.aver=(stu.score1+stu.score2+stu.score3)/3;
cout<<" │"<<setw(10)<<stu.num<<"│"<<setw(6)<<stu.name<<"│"<<setw(10)<<stu.score1<<
"│ "<<setw(9)<<stu.score2<<"│"<<setw(10)<<stu.score3<<"│"<<setw(13)<<stu.aver<<"│"<<endl;
cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" └──────────┴──────┴──────────┴──────────┴──────────┴─────────────┘"<<endl;
}
void doublechainlist::printmenu() //菜单函数
{
cout <<"\n\t\t"<<"请选择以下一个功能:"<<endl;
cout <<"\n\t\t"<<"1.显示线性表中的数据元素."<<endl;
cout <<"\t\t2.初始化双向链表,填入初始学生数据" << endl;
cout <<"\t\t3.插入数据元素." << endl;
cout <<"\t\t4.删除数据元素."<<endl;
cout <<"\t\t5.查找数据元素."<<endl;
cout <<"\t\t6.取某个学生的第n个前驱和第m个后继元素 "<<endl;
//cout <<"\t\t6.给定某一学号x,能同时找到该学生第i个前驱的学生信息,以及该学生第j个后继的学生信息 "<<endl;
cout <<"\t\t0.退出.\n"<<endl;
cout <<"\t\t===============================\n"<<endl;
}
bool doublechainlist::input(doublechainlist list1,int &i,student stu1)
{
bool flag;
char a[100];
while(cin>>a)
{
if(strcmp(a,"0")==0)
break;
else
{
strcpy(stu1.num,a);
cin>>stu1.name;
cin>>stu1.score1;
cin>>stu1.score2;
cin>>stu1.score3;
flag=list1.insert(i,stu1);
i++;
}
}
if(flag)
return true;
}
bool doublechainlist::search_information(char *k,student &stu2)
{
chainlist *current =head->first;
student stu1;
while(current)
{
stu1=current->data;
if(strcmp(stu1.num,k)==0)
{
stu2=current->data;
return true;
}
current=current->next;
}
return false;
}
bool doublechainlist::insert(int k,student stu1)
{
if (k < 0)
return false;
int index=1;
chainlist *current=head->first;
while(index<k&¤t)
{
index++;
current=current->next;
}
if (k > 0 && ! current)
return false;
chainlist *q=new chainlist;
q->data=stu1;
if(k)
{
q->next=current->next;
q->pre=current;
chainlist *p=current->next;
current->next=q;
if(p)
p->pre=q;
}
else
{
q->next=head->first;
q->pre=NULL;
chainlist *p=head->first;
if(p)
p->pre=q;
head->first=q;
}
head->length++;
return true;
}
void doublechainlist:: output()
{// 逐个地输出链表L中的数据元素
chainlist *current=head->first;
cout<<"\n\n";
cout<<" ┌────────────────────────────────────────────────────────────────┐"<<endl;
cout<<" │ 成 绩 单 │"<<endl;
cout<<" ├──────────┬──────┬──────────┬──────────┬──────────┬─────────────┤"<<endl;
cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" │ 学号 │姓 名 │ 成绩1 │ 成绩2 │ 成绩3 │ 平均成绩 │"<<endl;
cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" ├──────────┼──────┼──────────┼──────────┼──────────┼─────────────┤"<<endl;
if(!current)
printf("当前双向链表中没有存储数据\n");
while (current)
{
if(current->data.num!=0)
current->data.aver=(current->data.score1+current->data.score2+current->data.score3)/3;
cout<<" │"<<setw(10)<<current->data.num<<"│"<<setw(6)<<current->data.name<<"│"<<setw(10)<<current->data.score1<<
"│ "<<setw(9)<<current->data.score2<<"│"<<setw(10)<<current->data.score3<<"│"<<setw(13)<<current->data.aver<<"│"<<endl;
cout<<" ├──────────┼──────┼──────────┼──────────┼──────────┼─────────────┤"<<endl;
current=current->next ;
}
//cout<<" │ │ │ │ │ │ │"<<endl;
cout<<" └──────────┴──────┴──────────┴──────────┴──────────┴─────────────┘"<<endl;
cout<<endl;
}
bool doublechainlist::deletenode(int k)
{
chainlist *p;
if(k<1||!head->first)
return false;
chainlist *current = head->first;
if(k==1)
{
p=current->next;
if(p)
p->pre=NULL;
head->first=p;
}
else
{
chainlist *q=head->first;
for(int index = 1;index<k&&q;index++)
{
q=q->next;
}
if(!q)
return false;
current = q;
q=current->pre;
p=current->next;
q->next=p;
if(p)
p->pre=q;
}
delete current;
return true;
}
int main(){
//system("color 6B");
int i=0;
int m;
int n=0;
char a[10];
int flag;
student stu1;
student stu2;
doublechainlist list1;
list1.doublechianlist();
list1.printmenuname();
//list1.printmenu();
/*
flag=list1.input(list1,i,stu1);
list1.output ();
cout<<"共有学生"<<i<<"人"<<endl;
n=i;
cout<<"想删除第几位学生的信息?\n";
if(flag)
while(cin>>m)
{
if(m>n||m==0)
break;
list1.deletenode(m);
n--;
cout<<"是否结束删除(按0结束)"<<endl;
}
list1.Output ();
cout<<"共有学生"<<n<<"人"<<endl;
*/
list1.printmenu();
while(1)
{
//system("cls");
printf("\n\t请输入功能编号:");
gets(a);
/*if(a[1]!='\0'&&a[1]!='\r')
{
cout <<"\n"<<"please re_choose"<<endl;
//system("pause");
//system("cls");
continue;
}*/
//else
//{
if(a[0]=='0')
break;
if(list1.choose_function(list1,stu1,a[0],n,stu2))
list1.printmenu();
//}
}
//system("PAUSE");
return 0;
}