1.顺序存储
线性表顺序存储结构,和数组差不多,详细介绍线性表的创建,返回元素值,删除,插入基本操作,初学者可以分模块学习。
这是一种简单的写法
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
#define ELEMTP int
typedef struct
{
int elem[MAX];
int length;
}Seqlist;
Seqlist Inilist()//顺序表的初始化
{
Seqlist L;//定义1个顺序表
L.length = 0;
return L;
}
Seqlist create(Seqlist L)
{
ELEMTP x;
scanf_s("%d", &x);
while (x != -1)
{
L.elem[L.length] = x;
L.length++;
scanf_s("%d", &x);
}
return L;
}
void outline(Seqlist L)
{
for (int i = 0; i < L.length; i++)
{
printf("%2d", L.elem[i]);
}
printf(" length=%d\n", L.length);
}
int find(Seqlist L,ELEMTP x)
{
int i = 0;
while (i < L.length&&L.elem[i] != x)
i++;
if (i < L.length) return i + 1;
else return 0;
}
Seqlist del(Seqlist L, int i)
{
int j = 0;
if (i<1 || i>L.length)printf("位置错误\n");
for (j = i; j < L.length; j++)
{
L.elem[j-1] = L.elem[j];
}
L.length--;
return L;
}
Seqlist insert(Seqlist L, int i, ELEMTP x)//在第i个位置插入元素x;
{
int j;
if (L.length == MAX || i<1 || i>L.length)
{
printf("位置错误"); return L;
}
else
{
for (j = L.length; j >= i; j--)
L.elem[j ] = L.elem[j-1];
L.elem[i-1] = x;
L.length++;
}
return L;
}
Seqlist paixu(Seqlist L)//按照递增排序
{//冒泡排序法
for (int i = 0; i < L.length-1;i++)
for (int j = 0; j < L.length - 1 - i; j++)
{
if (L.elem[j]>L.elem[j + 1])
{
int t; t = L.elem[j]; L.elem[j] = L.elem[j + 1]; L.elem[j + 1] = t;
}
}
return L;
}
Seqlist merge(Seqlist La, Seqlist Lb)
{
Seqlist Lc;
int k=0,i=0,j=0;
La = paixu(La); Lb = paixu(Lb);
outline(La); outline(Lb);
while (i<La.length&&j<Lb.length)
if (La.elem[i] < Lb.elem[j])
Lc.elem[k++] = La.elem[i++];
else
if (La.elem[i] == Lb.elem[j])
{
Lc.elem[k++] = La.elem[i++]; j++;
}
else
Lc.elem[k++] = Lb.elem[j++];
while (i < La.length) Lc.elem[k++] = La.elem[i++];
while (j < Lb.length) Lc.elem[k++] = Lb.elem[i++];
Lc.length = k;
return Lc;
}
int main()
{
Seqlist La, Lb,Lc;//定义结构体变量
int cord;
do{
printf(" \n 1 建立线性表 \n");
printf(" 2 La插入线性表 \n");
printf(" 3 合并.线性表 \n");
printf(" 4.La查找x返回其位置\n");
printf(" 5.La删除位置为i的元素");
printf(" 6.La递增排序\n");
scanf_s("%d", &cord);
switch (cord)
{
case 1:
{
printf("创建第一个线性表La\n");
La = Inilist();//初始化
La = create(La);
printf("La元素为:");
outline(La);
printf("创建第二个线性表Lb\n");
Lb = Inilist();//初始化
Lb = create(Lb);
printf("Lb元素为:");
outline(Lb);
}break;
case 3:{
Lc = merge(La, Lb);
outline(Lc);
}break;
case 2:{
int i; ELEMTP x;
printf("插入的位置\n"); scanf_s("%d", &i); printf("插入的值 "); scanf_s("%d", &x);
La = insert(La, i, x); outline(La);
}break;
case 4:{
ELEMTP x; int i;
printf("查找的值 "); scanf_s("%d", &x);
i = find(La, x);
if (i) printf("%d位置为%d ", x, i);
else printf("no exist'n");
}break;
case 5:{ int i;
printf("位置");scanf_s("%d", &i);
La = del(La, i);
outline(La);
}break;
case 6:{
La = paixu(La);
outline(La);
}break;
}
} while (cord <= 10 && cord > 0);
return 0;
}
第二种写法,使用动态分配顺序存储结构
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define LIST_INIT_SIZE 10 //线性表存储空间的初始分配量
#define LISTINCREMENT 1 //线性表存储空间的分配增量
typedef struct Seqlist
{
int *data;
int length;
int listsize; //当前分配的存储容量,以sizeof(ElemType)为单位
}Seqlist;
int Inilist(Seqlist *L)//构造一个空的线性表
{
L->data = (int *)malloc(LIST_INIT_SIZE*sizeof(int));
L->length = 0;
L->listsize = LIST_INIT_SIZE;
printf("成功初始化线性表!\n");
return OK;
}
int Creat(Seqlist *L)//建立线性表
{
int i;
printf("输入要建立的线性表的长度");
scanf_s("%d", &L->length);
printf("请输入%d个数:", L->length);
for (i = 0; i < L->length; i++)
{
scanf_s("%d", &L->data[i]);
}
printf("赋值成功!\n");
return OK;
}
int Insert(Seqlist *L,int i,int e)//在位置i前插入新元素
{
int *newbase;
if (i<1 || i>L->length + 1){printf("插入位置不合法\n"); return 0;}
if (L->length >= L->listsize)//存储空间已满。增加分配
{
newbase = (int *)realloc(L->data, (L->listsize + LISTINCREMENT)*sizeof(int));//realloc函数
if (!newbase) return 0;
L->data = newbase; //新基址(data是指针)
L->listsize = L->listsize + LISTINCREMENT;//存储容量改变了
}
for (int j = L->length; j >= i; j--)
L->data[j] = L->data[j - 1];
L->data[i-1] = e;
L->length++;
printf("成功插入新元素%d", e);
return OK;
}
int Del(Seqlist *L, int i)//删除位置为i的元素
{
if (i<1 || i>L->length){ printf("删除位置不合法\n"); return 0; }
for (int j = i; j < L->length; j++)
{
L->data[j - 1] = L->data[j];
}
L->length--;
return OK;
}
int LocateElem(Seqlist *L, int e)//查找某元素,若找到返回第一次出现的位置
{
int j = 0;
while (j < L->length && (L->data[j] != e))
j++;
if (e == L->data[j]) return (j + 1);
else return 0;
}
void Print(Seqlist *L)//打印输出
{
for (int i = 0; i < L->length; i++)
printf("%2d ", L->data[i]);
printf("L->listsize=%d", L->listsize);
}
void Destory(Seqlist *L)
{
free(L->data);
printf("已销毁");
}
int main()
{
int cord;
Seqlist L;
do
{
printf(" \n * 1.初始化线性表 \n");
printf(" * 2.创建线性表 \n");
printf(" * 3.插入新元素 \n");
printf(" * 4.删除元素 \n");
printf(" * 5.查找元素首次出现的位置 \n");
printf(" * 6.打印输出顺序表中的元素值 \n");
printf(" * 7.销毁顺序表 \n");
printf(" * 8.退出 \n");
scanf_s("%d", &cord);
switch (cord)
{
case 1:Inilist(&L); break;
case 2:Creat(&L); break;
case 3:
{
int i, e;
printf("在位置i前插入新元素,输入i:");
scanf_s("%d", &i);
printf("要插入的新元素e:");
scanf_s("%d", &e);
Insert(&L, i, e);
}break;
case 4:
{
int i;
printf("输入要删除的位置i:");
scanf_s("%d", &i);
Del(&L, i);
}break;
case 5:
{
int e,flag;
printf("输入要查找的元素:");
scanf_s("%d", &e);
flag=LocateElem(&L, e);
if (flag)
printf("%d第一次出现的位置为%d", e,flag);
else printf("未找到");
}break;
case 6:Print(&L); break;
case 7:Destory(&L); break;
case 8:exit(0); break;
}
} while (cord <= 8 && cord > 0);
return 0;
}
2.链式存储
1.单链表结点的创建
头插法就是说插到第一个节点之前,头插法一直在头结点的后继位置插入新结点,,尾插法 就是插入到链表最后一个节点之后。
2.单链表结点的插入
3 单链表结点的删除
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
int n = 0;
struct Lnode
{
ElemType data;
struct Lnode *next;
};
struct Lnode *createEND()//尾插法建立链表
{
struct Lnode *head, *p2, *p;
ElemType x;
head = (struct Lnode *)malloc(sizeof(struct Lnode));//申请头结点空间
head->next = NULL; //头结点数据域为空
p = head;
printf("data= ");
scanf_s("%d", &x);
while (x != -1)
{
n++;
p2 = (struct Lnode *)malloc(sizeof(struct Lnode));//申请新结点
p2->data = x;
p->next = p2;//重点
p = p2;//重点
printf("data= ");
scanf_s("%d", &x);
}
p->next = NULL;
return head;
}
struct Lnode *createFRONT()//头插法建立链表
{
int x;
struct Lnode *head, *p2;
head = (struct Lnode *)malloc(sizeof(struct Lnode));
head->next = NULL;
printf("data= ");
scanf_s("%d", &x);
while (x != -1)
{
p2 = (struct Lnode *)malloc(sizeof(struct Lnode));
p2->data = x;
p2->next = head->next;//重点
head->next = p2;//重点
printf("data= ");
scanf_s("%d", &x);
}
return head;
}
void outline(struct Lnode *head)
{
struct Lnode *p;
p = head->next;
while (p != NULL)
{
printf("data=%-2d", p->data);
p = p->next;
}
printf("输出结束\n");
}
void getelem(struct Lnode *head, int i)//输出位置号为i的元素
{
int j = 1;//计数器,当j==i时结束
struct Lnode *p;
p = head->next;//
while (p&&j < i)
{
p = p->next;
j++;
}
if (j == i)
printf("%d位置为%d ", i, p->data);
else
printf("不存在\n");
}
void check_elem(struct Lnode *head, int i)
{
struct Lnode *p;
int j = 1;
p = head->next;
while (p)
{
if (p->data == i)
{
printf("%d的位置为%d", i, j);
return;
}
else
p = p->next;
j++;
}
printf("不存在此元素\n");
}
struct Lnode *insert(struct Lnode *head)//在位置i前插入元素e
{
int i, j; ElemType e;
printf("输入位置i ");
scanf_s("%d", &i);
printf("输入插入的元素e ");
scanf_s("%d", &e);
struct Lnode *pre, *p;//pre为前驱结点,p为新结点
p = (struct Lnode*)malloc(sizeof(struct Lnode));
pre = head;
j = 1;
while (j<i)
{
pre = pre->next;
j++;
}
p->data = e;
p->next = pre->next;//下面两句不能写错,注意理解(pre->next相当于原来pre后面的结点)
pre->next = p;
n++;
return head;
}
struct Lnode *del(struct Lnode *head)
{
int i, j;
printf("输入要删除的元素的位置i ");
scanf_s("%d", &i);
struct Lnode *p, *q;
p = head;
if (i<1 || i>n)
{
printf("删除位置不合理\n");
return head;
}
for (j = 1; j < i; j++)
{
p = p->next;
}
q = p->next;
p->next = q->next;//p->next=p->next->next;用q代替了p->next;
printf("已删除元素%d", q->data);
free(q);
n--;
return head;
}
struct Lnode *prune(struct Lnode *head)
{/* 指针r用来扫描p的后续结点,指针q始终指向r的前驱,以便删除r*/
struct Lnode *p, *q, *r;
p = head->next;
while (p&&p->next)//使用两个while循环来遍历
{
q = p; r = p->next;
while (r)
{
if (p->data == r->data)
{
q->next = r->next;
free(r);
r = q->next;//r指向被删结点的后继
}
else
{
q = r; r = r->next;//使r后移
}
}
p = p->next;//使p后移
}
return head;
}
struct Lnode *invert(struct Lnode *head)
{
struct Lnode *s, *p;
p = head->next;
head->next = NULL; //将逆表初值置空
while (p)
{
s = p; //s是当前要逆置的结点
p = p->next;//p指向下一个将要逆置的结点
s->next = head->next;//将s插入到头结点之后第一个结点(不是头结点)之前
head->next = s;//将s插入到头结点之后
}
return head;
}
int main()
{
int cord;
struct Lnode *list;
list = NULL;
do{
printf(" 1 尾插法建立链表 \n");
printf(" 2 头插法建立链表 \n");
printf(" 3 输出位置为i的元素 \n");
printf(" 4 查找元素i的位置 \n");
printf(" 5 在元素i的位置前插入元素e \n");
printf(" 6 删除位置为i的元素 \n");
printf(" 7 合并表中相同的元素 \n");
printf(" 8 逆置链表的元素 \n");
printf(" 9 输出链表 \n");
scanf_s("%d", &cord);
switch (cord)
{
case 1:{ list = createEND(); }break;
case 2:{ list = createFRONT(); }break;
case 3:
{
int i;
printf("输入位置\n");
scanf_s("%d", &i);
getelem(list, i);
}break;
case 4:
{
int i;
printf("输入要查找的元素\n");
scanf_s("%d", &i);
check_elem(list, i);
}break;
case 5:{ list = insert(list); }break;
case 6:{ list = del(list); }break;
case 7:{ list = prune(list); }break;
case 8:{ list = invert(list); }break;
case 9:{ outline(list); }break;
}
} while (cord <= 10 && cord > 0);
return 0;
}
//销毁链表
Status DestroyList(LinkList *L)
{ /* 初始条件:线性表L已存在。操作结果:销毁线性表L */
LinkList* q;
while(L)
{
q=L->next;
free(L);
L=q;
}
return OK;
}