线性表(顺序存储,链式存储)

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;
} 



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值